#include <linux/init.h>
#include <linux/module.h>
#include <linux/i2c.h>
#include <linux/platform_device.h>
#include <linux/videodev2.h>
#include <media/v4l2-subdev.h>
#include <media/soc_camera.h>
#include <media/v4l2-chip-ident.h>
#include <linux/delay.h>

/* add by cym 20130605 */
#include <linux/videodev2_samsung.h>
#include <linux/regulator/consumer.h>
#include <mach/gpio.h>
#include <plat/gpio-cfg.h>
#include <mach/regs-gpio.h>
#include <mach/regs-clock.h>
/* end add */

/* add by cym 20130605 */
enum {
	AUTO_FOCUS_FAILED,
	AUTO_FOCUS_DONE,
	AUTO_FOCUS_CANCELLED,
};

#ifndef CONFIG_TC4_EVT
//static struct regulator *vdd18_5m_cam_regulator = NULL;
//static struct regulator *vdd28_5m_cam_regulator = NULL;
struct regulator *ov_vddaf_cam_regulator = NULL;
struct regulator *ov_vdd5m_cam_regulator = NULL;

struct regulator *ov_vdd18_cam_regulator = NULL;
struct regulator *ov_vdd28_cam_regulator = NULL;

int down_af_firmware_flag = 0;
#endif
/* end add */

/* ANSI Color codes */
#define VT(CODES)  "\033[" CODES "m"
#define VT_NORMAL  VT("")
#define VT_RED     VT("0;32;31")
#define VT_GREEN   VT("1;32")
#define VT_YELLOW  VT("1;33")
#define VT_BLUE    VT("1;34")
#define VT_PURPLE  VT("0;35")


#define OV5640_DBG

#define xprintk(fmt, ...) \
    printk("%s()->%d " fmt, __func__, __LINE__, ## __VA_ARGS__)

#ifdef OV5640_DBG

#define _DBG(color, fmt, ...)  \
    xprintk(color "" fmt VT_NORMAL, ## __VA_ARGS__)

#define OV_INFO(fmt, args...)  _DBG(VT_GREEN, fmt, ## args)
#define OV_ERR(fmt, args...)   _DBG(VT_RED, fmt, ## args)
#else
#define OV_INFO(fmt, args...)  do {} while(0)
#define OV_ERR(fmt, args...) do {} while(0)
#endif

#define _INFO(color, fmt, ...) \
    xprintk(color "::" fmt ""VT_NORMAL, ## __VA_ARGS__)

/* mainly used in test code */
#define INFO_PURLPLE(fmt, args...) _INFO(VT_PURPLE, fmt, ## args)
#define INFO_RED(fmt, args...)     _INFO(VT_RED, fmt, ## args)
#define INFO_GREEN(fmt, args...)   _INFO(VT_GREEN, fmt, ## args)
#define INFO_BLUE(fmt, args...)    _INFO(VT_BLUE, fmt, ## args)


#define OV5640_I2C_NAME  "ov5640"

/* 
 * I2C write address: 0x78, read: 0x79 , give up least significant bit. 
 */
#define OV5640_I2C_ADDR  (0x78 >> 1)

/*
 * sensor ID
 */
#define OV5640  0x5640
#define VERSION(id, vers) ((id << 8) | (vers & 0XFF))


/* default format */
#define QVGA_WIDTH  320
#define QVGA_HEIGHT	240

#define VGA_WIDTH	640
#define VGA_HEIGHT	480

#define XGA_WIDTH	1024
#define XGA_HEIGHT	768

#define SXGA_WIDTH	1280
#define SXGA_HEIGHT	960

#define UXGA_WIDTH	1600
#define UXGA_HEIGHT	1200

#define QXGA_WIDTH	2048
#define QXGA_HEIGHT	1536

#define QSXGA_WIDTH	    2560
#define QSXGA_HEIGHT	1920  //normally 2048, but ov5640 only support simple qsxga

#define CAPTURE_FRAME_RATE  500   /* multiplied by 100 */
#define PREVIEW_FRAME_RATE  1500   /* multiplied by 100 */

#define OV5640_COLUMN_SKIP 0
#define OV5640_ROW_SKIP    0
#define OV5640_MAX_WIDTH   (QSXGA_WIDTH)
#define OV5640_MAX_HEIGHT  (QSXGA_HEIGHT)

#define OV5640_HFLIP 0x1
#define OV5640_VFLIP 0x2


enum ov5640_resolution {
    RESV_VGA = 1,
    RESV_XGA,
    RESV_SXGA,
    RESV_UXGA,
    RESV_QXGA,
    RESV_QSXGA,
};


struct regval {
    unsigned short reg;
    unsigned char  val;
};

struct ov5640_color_format {
	enum v4l2_mbus_pixelcode code;
	enum v4l2_colorspace colorspace;
};

struct ov5640_win_size {
	char *name;
    enum ov5640_resolution resv;
	unsigned int  width;
	unsigned int  height;
	const struct regval *regs;
};


struct ov5640_priv {
    struct v4l2_subdev  subdev;
    const struct ov5640_color_format *cfmt;
    const struct ov5640_win_size *win;
    int  model;
    int brightness;
    int contrast;
    int saturation;
    int hue;
    int exposure;
    int sharpness;
    int colorfx;
    int flip_flag;
};


static const struct regval ov5640_init_regs[] = {
    /* for the setting , 24M Mlck input and 24M Plck output */
    {0x3103, 0x11}, 
    {0x3008, 0x82}, /* soft reset */
    {0x3008, 0x42}, 
    {0x3103, 0x03}, /* input clock, from PLL */
    {0x3017, 0xff}, /* d[9:0] pins I/O ctrl */
    {0x3018, 0xff}, 
                    /* system control */
    {0x3034, 0x1a}, /* MIPI 10-bit mode */
    {0x3035, 0x11}, /* clock, PLL sets */
    {0x3036, 0x46}, 
    {0x3037, 0x13}, 
    {0x3108, 0x01}, /* SCCB CLK root divider */
    {0x3630, 0x36}, 
    {0x3631, 0x0e}, 
    {0x3632, 0xe2}, 
    {0x3633, 0x12}, 
    {0x3621, 0xe0}, 
    {0x3704, 0xa0}, 
    {0x3703, 0x5a}, 
    {0x3715, 0x78}, 
    {0x3717, 0x01}, 
    {0x370b, 0x60}, 
    {0x3705, 0x1a}, 
    {0x3905, 0x02}, 
    {0x3906, 0x10}, 
    {0x3901, 0x0a}, 
    {0x3731, 0x12}, 
    {0x3600, 0x08}, 
    {0x3601, 0x33}, 
    {0x302d, 0x60}, 
    {0x3620, 0x52}, 
    {0x371b, 0x20}, 
    {0x471c, 0x50}, 
    {0x3a13, 0x43}, 
    {0x3a18, 0x00}, 
    {0x3a19, 0xf8}, 
    {0x3635, 0x13}, 
    {0x3636, 0x03}, 
    {0x3634, 0x40}, 
    {0x3622, 0x01}, 
    
    {0x3c01, 0x34},  /* 50/60HZ detector */
    {0x3c04, 0x28}, 
    {0x3c05, 0x98}, 
    {0x3c06, 0x00}, 
    {0x3c07, 0x08}, 
    {0x3c08, 0x00}, 
    {0x3c09, 0x1c}, 
    {0x3c0a, 0x9c}, 
    {0x3c0b, 0x40}, 
    
    {0x3820, 0x41}, /* mirror and flip */
    {0x3821, 0x07}, 
    
    {0x3814, 0x31}, /* image windowing */
    {0x3815, 0x31}, 
    {0x3800, 0x00}, 
    {0x3801, 0x00}, 
    {0x3802, 0x00}, 
    {0x3803, 0x04}, 
    {0x3804, 0x0a}, 
    {0x3805, 0x3f}, 
    {0x3806, 0x07}, 
    {0x3807, 0x9b}, 
    {0x3808, 0x02}, /* 0x280==640 */
    {0x3809, 0x80}, 
    {0x380a, 0x01}, /* 0x1e0==480 */
    {0x380b, 0xe0}, 
    {0x380c, 0x07}, 
    {0x380d, 0x68}, 
    {0x380e, 0x03}, 
    {0x380f, 0xd8}, 
    {0x3810, 0x00}, 
    {0x3811, 0x10}, 
    {0x3812, 0x00}, 
    {0x3813, 0x06}, 
    
    {0x3618, 0x00}, 
    {0x3612, 0x29}, 
    {0x3708, 0x64}, 
    {0x3709, 0x52}, 
    {0x370c, 0x03}, 
    
    {0x3a02, 0x03}, /* AEC/AGC control */
    {0x3a03, 0xd8}, 
    {0x3a08, 0x01}, 
    {0x3a09, 0x27}, 
    {0x3a0a, 0x00}, 
    {0x3a0b, 0xf6}, 
    {0x3a0e, 0x03}, 
    {0x3a0d, 0x04}, 
    {0x3a14, 0x03}, 
    {0x3a15, 0xd8}, 
    
    {0x4001, 0x02}, /* BLC start line */
    {0x4004, 0x02}, /* BLC line number */
    {0x3000, 0x00}, /* block enable */
    {0x3002, 0x1c}, 
    {0x3004, 0xff}, /* clock enable */
    {0x3006, 0xc3}, 
    {0x300e, 0x58}, 
    {0x302e, 0x00}, 
    {0x4300, 0x32}, /* format ctrl: YUV422 UYVY */
    {0x501f, 0x00}, /* format MUX ctrl: ISP YUV422 */
    {0x4713, 0x03}, /* jpeg mode select: mode 3 */
    {0x4407, 0x04}, /* jpeg ctrl */
    {0x440e, 0x00}, 
    {0x460b, 0x35}, /* VFIFO ctrl */
    {0x460c, 0x22}, 
    {0x3824, 0x02}, 
    {0x5000, 0xa7}, /* ISP top ctrl */
    {0x5001, 0xa3}, 
    
    {0x5180, 0xff}, /* AWB ctrl */
    {0x5181, 0xf2}, 
    {0x5182, 0x00}, 
    {0x5183, 0x14}, 
    {0x5184, 0x25}, 
    {0x5185, 0x24}, 
    {0x5186, 0x09}, 
    {0x5187, 0x09}, 
    {0x5188, 0x09}, 
    {0x5189, 0x75}, 
    {0x518a, 0x54}, 
    {0x518b, 0xe0}, 
    {0x518c, 0xb2}, 
    {0x518d, 0x42}, 
    {0x518e, 0x3d}, 
    {0x518f, 0x56}, 
    {0x5190, 0x46}, 
    {0x5191, 0xf8}, 
    {0x5192, 0x04}, 
    {0x5193, 0x70}, 
    {0x5194, 0xf0}, 
    {0x5195, 0xf0}, 
    {0x5196, 0x03}, 
    {0x5197, 0x01}, 
    {0x5198, 0x04}, 
    {0x5199, 0x12}, 
    {0x519a, 0x04}, 
    {0x519b, 0x00}, 
    {0x519c, 0x06}, 
    {0x519d, 0x82}, 
    {0x519e, 0x38}, 
    
    {0x5381, 0x1e}, /* Color matrix */
    {0x5382, 0x5b}, 
    {0x5383, 0x08}, 
    {0x5384, 0x0a}, 
    {0x5385, 0x7e}, 
    {0x5386, 0x88}, 
    {0x5387, 0x7c}, 
    {0x5388, 0x6c}, 
    {0x5389, 0x10}, 
    {0x538a, 0x01}, 
    {0x538b, 0x98}, 
    
    {0x5300, 0x08}, /* Color interpolation */
    {0x5301, 0x30}, 
    {0x5302, 0x10}, 
    {0x5303, 0x00}, 
    {0x5304, 0x08}, 
    {0x5305, 0x30}, 
    {0x5306, 0x08}, 
    {0x5307, 0x16}, 
    {0x5309, 0x08}, 
    {0x530a, 0x30}, 
    {0x530b, 0x04}, 
    {0x530c, 0x06}, 
    
    {0x5480, 0x01}, /* gamma ctrl */
    {0x5481, 0x08}, 
    {0x5482, 0x14}, 
    {0x5483, 0x28}, 
    {0x5484, 0x51}, 
    {0x5485, 0x65}, 
    {0x5486, 0x71}, 
    {0x5487, 0x7d}, 
    {0x5488, 0x87}, 
    {0x5489, 0x91}, 
    {0x548a, 0x9a}, 
    {0x548b, 0xaa}, 
    {0x548c, 0xb8}, 
    {0x548d, 0xcd}, 
    {0x548e, 0xdd}, 
    {0x548f, 0xea}, 
    {0x5490, 0x1d}, 
    
    {0x5580, 0x02}, /* special digital effects(SDE) */
    {0x5583, 0x40}, 
    {0x5584, 0x10}, 
    {0x5589, 0x10}, 
    {0x558a, 0x00}, 
    {0x558b, 0xf8}, 
    
    {0x5800, 0x23}, /* LENC ctrl */
    {0x5801, 0x14}, 
    {0x5802, 0x0f}, 
    {0x5803, 0x0f}, 
    {0x5804, 0x12}, 
    {0x5805, 0x26}, 
    {0x5806, 0x0c}, 
    {0x5807, 0x08}, 
    {0x5808, 0x05}, 
    {0x5809, 0x05}, 
    {0x580a, 0x08}, 
    {0x580b, 0x0d}, 
    {0x580c, 0x08}, 
    {0x580d, 0x03}, 
    {0x580e, 0x00}, 
    {0x580f, 0x00}, 
    {0x5810, 0x03}, 
    {0x5811, 0x09}, 
    {0x5812, 0x07}, 
    {0x5813, 0x03}, 
    {0x5814, 0x00}, 
    {0x5815, 0x01}, 
    {0x5816, 0x03}, 
    {0x5817, 0x08}, 
    {0x5818, 0x0d}, 
    {0x5819, 0x08}, 
    {0x581a, 0x05}, 
    {0x581b, 0x06}, 
    {0x581c, 0x08}, 
    {0x581d, 0x0e}, 
    {0x581e, 0x29}, 
    {0x581f, 0x17}, 
    {0x5820, 0x11}, 
    {0x5821, 0x11}, 
    {0x5822, 0x15}, 
    {0x5823, 0x28}, 
    {0x5824, 0x46}, 
    {0x5825, 0x26}, 
    {0x5826, 0x08}, 
    {0x5827, 0x26}, 
    {0x5828, 0x64}, 
    {0x5829, 0x26}, 
    {0x582a, 0x24}, 
    {0x582b, 0x22}, 
    {0x582c, 0x24}, 
    {0x582d, 0x24}, 
    {0x582e, 0x06}, 
    {0x582f, 0x22}, 
    {0x5830, 0x40}, 
    {0x5831, 0x42}, 
    {0x5832, 0x24}, 
    {0x5833, 0x26}, 
    {0x5834, 0x24}, 
    {0x5835, 0x22}, 
    {0x5836, 0x22}, 
    {0x5837, 0x26}, 
    {0x5838, 0x44}, 
    {0x5839, 0x24}, 
    {0x583a, 0x26}, 
    {0x583b, 0x28}, 
    {0x583c, 0x42}, 
    {0x583d, 0xce}, 
    {0x5025, 0x00}, 
    
    {0x3a0f, 0x30}, /* AEC functions */
    {0x3a10, 0x28}, 
    {0x3a1b, 0x30}, 
    {0x3a1e, 0x26}, 
    {0x3a11, 0x60}, 
    {0x3a1f, 0x14}, 
    
    {0x3008, 0x02}, /* soft reset/pwd default value */
    {0x3035, 0x21}, /* SC PLL ctrl */
    
    {0x3c01, 0xb4}, /* Band, 0x50Hz */
    {0x3c00, 0x04}, 
    
    {0x3a19, 0x7c}, /* gain ceiling */
    
    {0x5800, 0x2c}, /* OV5640 LENC setting */
    {0x5801, 0x17}, 
    {0x5802, 0x11}, 
    {0x5803, 0x11}, 
    {0x5804, 0x15}, 
    {0x5805, 0x29}, 
    {0x5806, 0x08}, 
    {0x5807, 0x06}, 
    {0x5808, 0x04}, 
    {0x5809, 0x04}, 
    {0x580a, 0x05}, 
    {0x580b, 0x07}, 
    {0x580c, 0x06}, 
    {0x580d, 0x03}, 
    {0x580e, 0x01}, 
    {0x580f, 0x01}, 
    {0x5810, 0x03}, 
    {0x5811, 0x06}, 
    {0x5812, 0x06}, 
    {0x5813, 0x02}, 
    {0x5814, 0x01}, 
    {0x5815, 0x01}, 
    {0x5816, 0x04}, 
    {0x5817, 0x07}, 
    {0x5818, 0x06}, 
    {0x5819, 0x07}, 
    {0x581a, 0x06}, 
    {0x581b, 0x06}, 
    {0x581c, 0x06}, 
    {0x581d, 0x0e}, 
    {0x581e, 0x31}, 
    {0x581f, 0x12}, 
    {0x5820, 0x11}, 
    {0x5821, 0x11}, 
    {0x5822, 0x11}, 
    {0x5823, 0x2f}, 
    {0x5824, 0x12}, 
    {0x5825, 0x25}, 
    {0x5826, 0x39}, 
    {0x5827, 0x29}, 
    {0x5828, 0x27}, 
    {0x5829, 0x39}, 
    {0x582a, 0x26}, 
    {0x582b, 0x33}, 
    {0x582c, 0x24}, 
    {0x582d, 0x39}, 
    {0x582e, 0x28}, 
    {0x582f, 0x21}, 
    {0x5830, 0x40}, 
    {0x5831, 0x21}, 
    {0x5832, 0x17}, 
    {0x5833, 0x17}, 
    {0x5834, 0x15}, 
    {0x5835, 0x11}, 
    {0x5836, 0x24}, 
    {0x5837, 0x27}, 
    {0x5838, 0x26}, 
    {0x5839, 0x26}, 
    {0x583a, 0x26}, 
    {0x583b, 0x28}, 
    {0x583c, 0x14}, 
    {0x583d, 0xee}, 
    {0x4005, 0x1a}, /* BLC always update */
    
    {0x5381, 0x26}, /* color matrix ctrl */
    {0x5382, 0x50}, 
    {0x5383, 0x0c}, 
    {0x5384, 0x09}, 
    {0x5385, 0x74}, 
    {0x5386, 0x7d}, 
    {0x5387, 0x7e}, 
    {0x5388, 0x75}, 
    {0x5389, 0x09}, 
    {0x538b, 0x98}, 
    {0x538a, 0x01}, 
    
    {0x5580, 0x02}, /* (SDE)UVAdjust Auto Mode */
    {0x5588, 0x01}, 
    {0x5583, 0x40}, 
    {0x5584, 0x10}, 
    {0x5589, 0x0f}, 
    {0x558a, 0x00}, 
    {0x558b, 0x3f}, 
    
    {0x5308, 0x25}, /* De-Noise, 0xAuto */
    {0x5304, 0x08}, 
    {0x5305, 0x30}, 
    {0x5306, 0x10}, 
    {0x5307, 0x20}, 
    
    {0x5180, 0xff}, /* awb ctrl */
    {0x5181, 0xf2}, 
    {0x5182, 0x11}, 
    {0x5183, 0x14}, 
    {0x5184, 0x25}, 
    {0x5185, 0x24}, 
    {0x5186, 0x10}, 
    {0x5187, 0x12}, 
    {0x5188, 0x10}, 
    {0x5189, 0x80}, 
    {0x518a, 0x54}, 
    {0x518b, 0xb8}, 
    {0x518c, 0xb2}, 
    {0x518d, 0x42}, 
    {0x518e, 0x3a}, 
    {0x518f, 0x56}, 
    {0x5190, 0x46}, 
    {0x5191, 0xf0}, 
    {0x5192, 0xf}, 
    {0x5193, 0x70}, 
    {0x5194, 0xf0}, 
    {0x5195, 0xf0}, 
    {0x5196, 0x3}, 
    {0x5197, 0x1}, 
    {0x5198, 0x6}, 
    {0x5199, 0x62}, 
    {0x519a, 0x4}, 
    {0x519b, 0x0}, 
    {0x519c, 0x4}, 
    {0x519d, 0xe7}, 
    {0x519e, 0x38}, 

};

static const struct regval ov5640_qsxga_regs[] = {
    {0x3820, 0x40},  /* diff. init */
    {0x3821, 0x06},
    {0x3814, 0x11}, /* image windowing */
    {0x3815, 0x11},
    {0x3803, 0x00},
    {0x3807, 0x9f},
    {0x3808, 0x0a}, /* 0x0a20==2592 */
    {0x3809, 0x20},
    {0x380a, 0x07}, /* 0x798==1944 */
    {0x380b, 0x98},
    {0x380c, 0x0b},
    {0x380d, 0x1c},
    {0x380e, 0x07},
    {0x380f, 0xb0},
    {0x3813, 0x04},
    
    {0x3618, 0x04},
    {0x3612, 0x4b},
    {0x3708, 0x21},
    {0x3709, 0x12},
    {0x370c, 0x00},
    {0x3a02, 0x07}, /* night mode */
    {0x3a03, 0xb0},
    {0x3a0e, 0x06},
    {0x3a0d, 0x08},
    {0x3a14, 0x07},
    {0x3a15, 0xb0},
    
    {0x4004, 0x06}, /* BLC line number */
    {0x5000, 0x07}, /* black/white pixel cancell, color interp. enable */
    {0x5181, 0x52}, /* AWB */
    {0x5182, 0x00},
    {0x5197, 0x01},
    {0x519e, 0x38},
    
    {0x3035, 0x21}, /* SC PLL */
    {0x5000, 0x27}, 
    {0x5001, 0x83}, /* special effect, color matrix, AWB enable */
    {0x3035, 0x71},
    {0x4713, 0x02}, /* jpeg mode 2 */
    {0x3036, 0x69},
    {0x4407, 0x0c}, /* jpeg ctrl */
    {0x460b, 0x37},
    {0x460c, 0x20},
    {0x3824, 0x01},
    {0x4005, 0x1A},

};

/*
static const struct regval ov5640_qsxga_to_qvga_regs[] = {

};
*/

static const struct regval ov5640_qsxga_to_vga_regs[] = {
    {0x3800, 0x00}, /* image windowing */
    {0x3801, 0x00},
    {0x3802, 0x00},
    {0x3803, 0x00},
    {0x3804, 0xA },
    {0x3805, 0x3f},
    {0x3806, 0x7 },
    {0x3807, 0x9f},
    {0x3808, 0x2 }, /* 0x280== 640*/
    {0x3809, 0x80},
    {0x380a, 0x1 }, /* 0x1e0== 480*/
    {0x380b, 0xe0},
    {0x380c, 0xc },
    {0x380d, 0x80},
    {0x380e, 0x7 },
    {0x380f, 0xd0},
    
    {0x5001, 0xa3}, /* SDE, scaling, color matrix, AWB enable */
    {0x5680, 0x0 }, /* AVG ctrl */
    {0x5681, 0x0 },
    {0x5682, 0xA },
    {0x5683, 0x20},
    {0x5684, 0x0 },
    {0x5685, 0x0 },
    {0x5686, 0x7 },
    {0x5687, 0x98},

};


static const struct regval ov5640_qsxga_to_xga_regs[] = {
    {0x3800, 0x00},
    {0x3801, 0x00},
    {0x3802, 0x00},
    {0x3803, 0x00},
    {0x3804, 0xA },
    {0x3805, 0x3f},
    {0x3806, 0x7 },
    {0x3807, 0x9f},
    {0x3808, 0x4 }, /* 0x400==1024 */
    {0x3809, 0x0 },
    {0x380a, 0x3 }, /* 0x300== 768*/
    {0x380b, 0x0 },
    {0x380c, 0xc },
    {0x380d, 0x80},
    {0x380e, 0x7 },
    {0x380f, 0xd0},
    {0x5001, 0xa3},
    {0x5680, 0x0 },
    {0x5681, 0x0 },
    {0x5682, 0xA },
    {0x5683, 0x20},
    {0x5684, 0x0 },
    {0x5685, 0x0 },
    {0x5686, 0x7 },
    {0x5687, 0x98},

};


static const struct regval ov5640_qsxga_to_sxga_regs[] = {
    {0x3800, 0x00},
    {0x3801, 0x00},
    {0x3802, 0x00},
    {0x3803, 0x00},
    {0x3804, 0xA },
    {0x3805, 0x3f},
    {0x3806, 0x7 },
    {0x3807, 0x9f},
    {0x3808, 0x5 }, /* 0x500==1280 */
    {0x3809, 0x0 },
    {0x380a, 0x3 }, /* 0x3c0==960 */
    {0x380b, 0xc0},
    {0x380c, 0xc },
    {0x380d, 0x80},
    {0x380e, 0x7 },
    {0x380f, 0xd0},
    {0x5001, 0xa3},
    {0x5680, 0x0 },
    {0x5681, 0x0 },
    {0x5682, 0xA },
    {0x5683, 0x20},
    {0x5684, 0x0 },
    {0x5685, 0x0 },
    {0x5686, 0x7 },
    {0x5687, 0x98},

};

static const struct regval ov5640_qsxga_to_uxga_regs[] = {
#if 0
    {0x3800, 0x00},
    {0x3801, 0x00},
    {0x3802, 0x00},
    {0x3803, 0x00},
    {0x3804, 0xA },
    {0x3805, 0x3f},
    {0x3806, 0x7 },
    {0x3807, 0x9f},
    {0x3808, 0x6 }, /* 0x640== 1600*/
    {0x3809, 0x40},
    {0x380a, 0x4 }, /* 0x4b0==1200 */
    {0x380b, 0xb0},
    {0x380c, 0xc },
    {0x380d, 0x80},
    {0x380e, 0x7 },
    {0x380f, 0xd0},
    {0x5001, 0xa3},
    {0x5680, 0x0 },
    {0x5681, 0x0 },
    {0x5682, 0xA },
    {0x5683, 0x20},
    {0x5684, 0x0 },
    {0x5685, 0x0 },
    {0x5686, 0x7 },
    {0x5687, 0x98},
#else
	{0x3503, 0x07},
	{0x3a00, 0x38},
	{0x4050, 0x6e},
	{0x4051, 0x8f},
	{0x5302, 0x1c},
	{0x5303, 0x08},
	{0x5306, 0x0c},
	{0x5307, 0x1c},
	{0x3820, 0x40},
	{0x3821, 0x06},
	{0x3800, 0x00},
	{0x3801, 0x00},
	{0x3802, 0x00},
	{0x3803, 0x00},
	{0x3804, 0x0a},
	{0x3805, 0x3f},
	{0x3806, 0x07},
	{0x3807, 0x9f},
	{0x3808, 0x0a},
	{0x3809, 0x20},
	{0x380a, 0x07},
	{0x380b, 0x98},
	{0x3810, 0x00},
	{0x3811, 0x10},
	{0x3812, 0x00},
	{0x3813, 0x04},
	{0x3814, 0x11},
	{0x3815, 0x11},

	{0x3034, 0x1a},
	{0x3035, 0x11},
	{0x3036, 0x46},
	{0x3037, 0x13},
	{0x3038, 0x00},
	{0x3039, 0x00},

	{0x380c, 0x0b},
	{0x380d, 0x1c},
	{0x380e, 0x07},
	{0x380f, 0xb0},

	{0x3a08, 0x00},
	{0x3a09, 0xc5},
	{0x3a0e, 0x0a},
	{0x3a0a, 0x00},
	{0x3a0b, 0xa4},
	{0x3a0d, 0x0c},

	{0x3618, 0x04},
	{0x3612, 0x2b},
	{0x3709, 0x12},
	{0x370c, 0x00},

	{0x4004, 0x06},
	{0x3002, 0x00},
	{0x3006, 0xff},
	{0x4713, 0x02},
	{0x4407, 0x04},
	{0x460b, 0x37},
	{0x460c, 0x22},
	{0x4837, 0x16},
	{0x3824, 0x01},
	{0x5001, 0x83},

	{0x4202,0x00},
#endif
};


static const struct regval ov5640_qsxga_to_qxga_regs[] = {
    {0x3800, 0x00},
    {0x3801, 0x00},
    {0x3802, 0x00},
    {0x3803, 0x00},
    {0x3804, 0xA },
    {0x3805, 0x3f},
    {0x3806, 0x7 },
    {0x3807, 0x9f},
    {0x3808, 0x8 }, /* 0x800==2048 */
    {0x3809, 0x0 },
    {0x380a, 0x6 }, /* 0x600==1536 */
    {0x380b, 0x0 },
    {0x380c, 0xc },
    {0x380d, 0x80},
    {0x380e, 0x7 },
    {0x380f, 0xd0},
    {0x5001, 0xa3},
    {0x5680, 0x0 },
    {0x5681, 0x0 },
    {0x5682, 0xA },
    {0x5683, 0x20},
    {0x5684, 0x0 },
    {0x5685, 0x0 },
    {0x5686, 0x7 },
    {0x5687, 0x98},

};

#if 0
static const struct v4l2_queryctrl ov5640_controls[] = {
	{
		.id		= V4L2_CID_VFLIP,
		.type		= V4L2_CTRL_TYPE_BOOLEAN,
		.name		= "Flip Vertically",
		.minimum	= 0,
		.maximum	= 1,
		.step		= 1,
		.default_value	= 0,
	},
	{
		.id		= V4L2_CID_HFLIP,
		.type		= V4L2_CTRL_TYPE_BOOLEAN,
		.name		= "Flip Horizontally",
		.minimum	= 0,
		.maximum	= 1,
		.step		= 1,
		.default_value	= 0,
	},
};
#endif

/* QVGA: 320*240 */ 
/*
static const struct ov5640_win_size ov5640_win_qvga = {
	.name     = "QVGA",
	.width    = QVGA_WIDTH,
	.height   = QVGA_HEIGHT,
	.regs     = ov5640_qsxga_to_qvga_regs,
};
*/

static const struct ov5640_win_size ov5640_wins[] = {
    {
        .name    = "VGA",    /* VGA: 640*480 */
        .resv    = RESV_VGA,
        .width   = VGA_WIDTH, 
        .height  = VGA_HEIGHT,
        .regs    = ov5640_qsxga_to_vga_regs,
    },
    {
        .name    = "XGA",    /* XGA: 1024*768 */
        .resv    = RESV_XGA,
        .width   = XGA_WIDTH,
        .height  = XGA_HEIGHT,
        .regs    = ov5640_qsxga_to_xga_regs,
    },
    {
        .name    = "SXGA",    /* SXGA: 1280*960  */
        .resv    = RESV_SXGA,
        .width   = SXGA_WIDTH,
        .height  = SXGA_HEIGHT,
        .regs    = ov5640_qsxga_to_sxga_regs,
    },
    {
        .name    = "UXGA",    /* UXGA: 1600*1200 */
        .resv    = RESV_UXGA,
        .width   = UXGA_WIDTH,
        .height  = UXGA_HEIGHT,
        .regs    = ov5640_qsxga_to_uxga_regs,
    },
    {
        .name    = "QXGA",    /* QXGA: 2048*1536 */
        .resv    = RESV_QXGA,
        .width   = QXGA_WIDTH,
        .height  = QXGA_HEIGHT,
        .regs    = ov5640_qsxga_to_qxga_regs,
    },
    {
        .name    = "QSXGA",    /* QSXGA: 2560*1920*/
        .resv    = RESV_QSXGA,
        .width   = QSXGA_WIDTH,
        .height  = QSXGA_HEIGHT,
        .regs    = ov5640_qsxga_regs,
    },

};


/*
 * supported color format list
 */
static const struct ov5640_color_format ov5640_cfmts[] = {
	{
		.code		= 2,//cym V4L2_MBUS_FMT_YUYV8_2X8_BE,
		.colorspace	= V4L2_COLORSPACE_JPEG,
	},
	{
		.code		= 3, //cym V4L2_MBUS_FMT_YUYV8_2X8_LE,
		.colorspace	= V4L2_COLORSPACE_JPEG,
	},
	{
                .code           = 0x2007, //cym V4L2_MBUS_FMT_YUYV8_2X8_LE,
                .colorspace     = V4L2_COLORSPACE_JPEG,
       },
};


static int i2cc_get_reg(struct i2c_client *client,
    unsigned short reg, unsigned char *value)
{
    unsigned char buffer[2];
    int ret = 0;
    int err = 0;

    buffer[0] = (reg >> 8) & 0xFF;
    buffer[1] = reg & 0xFF;
    if (2 != (ret = i2c_master_send(client, buffer, 2))) {
        err = -2;
        OV_ERR("i2cc out error: ret == %d (should be 2)\n", ret);
    }

    if (1 != (ret = i2c_master_recv(client, buffer, 1))) {
        err = -1;
        OV_ERR("i2cc in error: ret == %d (should be 1)\n", ret);
    }
    //OV_INFO("ov5640 client: read 0x%x = 0x%x\n", reg, buffer[0]);
    *value = buffer[0];

    return (err);
}


static int i2cc_set_reg(struct i2c_client *client,
    unsigned short reg, unsigned char value)
{
    unsigned char buffer[3];
    int ret = 0;
    int err = 0;

    buffer[0] = (reg >> 8) & 0xFF;
    buffer[1] = reg & 0xFF;
    buffer[2] = value;
    //OV_INFO("ov5640 client: writing 0x%x = 0x%x\n", reg, value);
    if (3 != (ret = i2c_master_send(client, buffer, 3))) {
        OV_ERR("i2cc out error: ret = %d (should be 3)\n", ret);
        err = -3;
    }
    return (err);
}






#if 1
/* add by dg 2015-07-15*/

/*************************************************************************
* FUNCTION
*   OV5640_FOCUS_AD5820_Init
*
* DESCRIPTION
*   This function is to load micro code for AF function
*
* PARAMETERS
*   None
*
* RETURNS
*   None
*
* GLOBALS AFFECTED
*
*************************************************************************/
static u8 AD5820_Config[] =
{
    0x02, 0x0f, 0xd6, 0x02, 0x0a, 0x39, 0xc2, 0x01, 0x22, 0x22, 0x00, 0x02, 0x0f, 0xb2, 0xe5, 0x1f, //0x8000,
    0x70, 0x72, 0xf5, 0x1e, 0xd2, 0x35, 0xff, 0xef, 0x25, 0xe0, 0x24, 0x4e, 0xf8, 0xe4, 0xf6, 0x08, //0x8010,
    0xf6, 0x0f, 0xbf, 0x34, 0xf2, 0x90, 0x0e, 0x93, 0xe4, 0x93, 0xff, 0xe5, 0x4b, 0xc3, 0x9f, 0x50, //0x8020,
    0x04, 0x7f, 0x05, 0x80, 0x02, 0x7f, 0xfb, 0x78, 0xbd, 0xa6, 0x07, 0x12, 0x0f, 0x04, 0x40, 0x04, //0x8030,
    0x7f, 0x03, 0x80, 0x02, 0x7f, 0x30, 0x78, 0xbc, 0xa6, 0x07, 0xe6, 0x18, 0xf6, 0x08, 0xe6, 0x78, //0x8040,
    0xb9, 0xf6, 0x78, 0xbc, 0xe6, 0x78, 0xba, 0xf6, 0x78, 0xbf, 0x76, 0x33, 0xe4, 0x08, 0xf6, 0x78, //0x8050,
    0xb8, 0x76, 0x01, 0x75, 0x4a, 0x02, 0x78, 0xb6, 0xf6, 0x08, 0xf6, 0x74, 0xff, 0x78, 0xc1, 0xf6, //0x8060,
    0x08, 0xf6, 0x75, 0x1f, 0x01, 0x78, 0xbc, 0xe6, 0x75, 0xf0, 0x05, 0xa4, 0xf5, 0x4b, 0x12, 0x0a, //0x8070,
    0xff, 0xc2, 0x37, 0x22, 0x78, 0xb8, 0xe6, 0xd3, 0x94, 0x00, 0x40, 0x02, 0x16, 0x22, 0xe5, 0x1f, //0x8080,
    0xb4, 0x05, 0x23, 0xe4, 0xf5, 0x1f, 0xc2, 0x01, 0x78, 0xb6, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x78, //0x8090,
    0x4e, 0xa6, 0x06, 0x08, 0xa6, 0x07, 0xa2, 0x37, 0xe4, 0x33, 0xf5, 0x3c, 0x90, 0x30, 0x28, 0xf0, //0x80a0,
    0x75, 0x1e, 0x10, 0xd2, 0x35, 0x22, 0xe5, 0x4b, 0x75, 0xf0, 0x05, 0x84, 0x78, 0xbc, 0xf6, 0x90, //0x80b0,
    0x0e, 0x8c, 0xe4, 0x93, 0xff, 0x25, 0xe0, 0x24, 0x0a, 0xf8, 0xe6, 0xfc, 0x08, 0xe6, 0xfd, 0x78, //0x80c0,
    0xbc, 0xe6, 0x25, 0xe0, 0x24, 0x4e, 0xf8, 0xa6, 0x04, 0x08, 0xa6, 0x05, 0xef, 0x12, 0x0f, 0x0b, //0x80d0,
    0xd3, 0x78, 0xb7, 0x96, 0xee, 0x18, 0x96, 0x40, 0x0d, 0x78, 0xbc, 0xe6, 0x78, 0xb9, 0xf6, 0x78, //0x80e0,
    0xb6, 0xa6, 0x06, 0x08, 0xa6, 0x07, 0x90, 0x0e, 0x8c, 0xe4, 0x93, 0x12, 0x0f, 0x0b, 0xc3, 0x78, //0x80f0,
    0xc2, 0x96, 0xee, 0x18, 0x96, 0x50, 0x0d, 0x78, 0xbc, 0xe6, 0x78, 0xba, 0xf6, 0x78, 0xc1, 0xa6, //0x8100,
    0x06, 0x08, 0xa6, 0x07, 0x78, 0xb6, 0xe6, 0xfe, 0x08, 0xe6, 0xc3, 0x78, 0xc2, 0x96, 0xff, 0xee, //0x8110,
    0x18, 0x96, 0x78, 0xc3, 0xf6, 0x08, 0xa6, 0x07, 0x90, 0x0e, 0x95, 0xe4, 0x18, 0x12, 0x0e, 0xe9, //0x8120,
    0x40, 0x02, 0xd2, 0x37, 0x78, 0xbc, 0xe6, 0x08, 0x26, 0x08, 0xf6, 0xe5, 0x1f, 0x64, 0x01, 0x70, //0x8130,
    0x4a, 0xe6, 0xc3, 0x78, 0xc0, 0x12, 0x0e, 0xdf, 0x40, 0x05, 0x12, 0x0e, 0xda, 0x40, 0x39, 0x12, //0x8140,
    0x0f, 0x02, 0x40, 0x04, 0x7f, 0xfe, 0x80, 0x02, 0x7f, 0x02, 0x78, 0xbd, 0xa6, 0x07, 0x78, 0xb9, //0x8150,
    0xe6, 0x24, 0x03, 0x78, 0xbf, 0xf6, 0x78, 0xb9, 0xe6, 0x24, 0xfd, 0x78, 0xc0, 0xf6, 0x12, 0x0f, //0x8160,
    0x02, 0x40, 0x06, 0x78, 0xc0, 0xe6, 0xff, 0x80, 0x04, 0x78, 0xbf, 0xe6, 0xff, 0x78, 0xbe, 0xa6, //0x8170,
    0x07, 0x75, 0x1f, 0x02, 0x78, 0xb8, 0x76, 0x01, 0x02, 0x02, 0x4a, 0xe5, 0x1f, 0x64, 0x02, 0x60, //0x8180,
    0x03, 0x02, 0x02, 0x2a, 0x78, 0xbe, 0xe6, 0xff, 0xc3, 0x78, 0xc0, 0x12, 0x0e, 0xe0, 0x40, 0x08, //0x8190,
    0x12, 0x0e, 0xda, 0x50, 0x03, 0x02, 0x02, 0x28, 0x12, 0x0f, 0x02, 0x40, 0x04, 0x7f, 0xff, 0x80, //0x81a0,
    0x02, 0x7f, 0x01, 0x78, 0xbd, 0xa6, 0x07, 0x78, 0xb9, 0xe6, 0x04, 0x78, 0xbf, 0xf6, 0x78, 0xb9, //0x81b0,
    0xe6, 0x14, 0x78, 0xc0, 0xf6, 0x18, 0x12, 0x0f, 0x04, 0x40, 0x04, 0xe6, 0xff, 0x80, 0x02, 0x7f, //0x81c0,
    0x00, 0x78, 0xbf, 0xa6, 0x07, 0xd3, 0x08, 0xe6, 0x64, 0x80, 0x94, 0x80, 0x40, 0x04, 0xe6, 0xff, //0x81d0,
    0x80, 0x02, 0x7f, 0x00, 0x78, 0xc0, 0xa6, 0x07, 0xc3, 0x18, 0xe6, 0x64, 0x80, 0x94, 0xb3, 0x50, //0x81e0,
    0x04, 0xe6, 0xff, 0x80, 0x02, 0x7f, 0x33, 0x78, 0xbf, 0xa6, 0x07, 0xc3, 0x08, 0xe6, 0x64, 0x80, //0x81f0,
    0x94, 0xb3, 0x50, 0x04, 0xe6, 0xff, 0x80, 0x02, 0x7f, 0x33, 0x78, 0xc0, 0xa6, 0x07, 0x12, 0x0f, //0x8200,
    0x02, 0x40, 0x06, 0x78, 0xc0, 0xe6, 0xff, 0x80, 0x04, 0x78, 0xbf, 0xe6, 0xff, 0x78, 0xbe, 0xa6, //0x8210,
    0x07, 0x75, 0x1f, 0x03, 0x78, 0xb8, 0x76, 0x01, 0x80, 0x20, 0xe5, 0x1f, 0x64, 0x03, 0x70, 0x26, //0x8220,
    0x78, 0xbe, 0xe6, 0xff, 0xc3, 0x78, 0xc0, 0x12, 0x0e, 0xe0, 0x40, 0x05, 0x12, 0x0e, 0xda, 0x40, //0x8230,
    0x09, 0x78, 0xb9, 0xe6, 0x78, 0xbe, 0xf6, 0x75, 0x1f, 0x04, 0x78, 0xbe, 0xe6, 0x75, 0xf0, 0x05, //0x8240,
    0xa4, 0xf5, 0x4b, 0x02, 0x0a, 0xff, 0xe5, 0x1f, 0xb4, 0x04, 0x10, 0x90, 0x0e, 0x94, 0xe4, 0x78, //0x8250,
    0xc3, 0x12, 0x0e, 0xe9, 0x40, 0x02, 0xd2, 0x37, 0x75, 0x1f, 0x05, 0x22, 0x30, 0x01, 0x03, 0x02, //0x8260,
    0x04, 0xc0, 0x30, 0x02, 0x03, 0x02, 0x04, 0xc0, 0x90, 0x51, 0xa5, 0xe0, 0x78, 0x93, 0xf6, 0xa3, //0x8270,
    0xe0, 0x08, 0xf6, 0xa3, 0xe0, 0x08, 0xf6, 0xe5, 0x1f, 0x70, 0x3c, 0x75, 0x1e, 0x20, 0xd2, 0x35, //0x8280,
    0x12, 0x0c, 0x7a, 0x78, 0x7e, 0xa6, 0x06, 0x08, 0xa6, 0x07, 0x78, 0x8b, 0xa6, 0x09, 0x18, 0x76, //0x8290,
    0x01, 0x12, 0x0c, 0x5b, 0x78, 0x4e, 0xa6, 0x06, 0x08, 0xa6, 0x07, 0x78, 0x8b, 0xe6, 0x78, 0x6e, //0x82a0,
    0xf6, 0x75, 0x1f, 0x01, 0x78, 0x93, 0xe6, 0x78, 0x90, 0xf6, 0x78, 0x94, 0xe6, 0x78, 0x91, 0xf6, //0x82b0,
    0x78, 0x95, 0xe6, 0x78, 0x92, 0xf6, 0x22, 0x79, 0x90, 0xe7, 0xd3, 0x78, 0x93, 0x96, 0x40, 0x05, //0x82c0,
    0xe7, 0x96, 0xff, 0x80, 0x08, 0xc3, 0x79, 0x93, 0xe7, 0x78, 0x90, 0x96, 0xff, 0x78, 0x88, 0x76, //0x82d0,
    0x00, 0x08, 0xa6, 0x07, 0x79, 0x91, 0xe7, 0xd3, 0x78, 0x94, 0x96, 0x40, 0x05, 0xe7, 0x96, 0xff, //0x82e0,
    0x80, 0x08, 0xc3, 0x79, 0x94, 0xe7, 0x78, 0x91, 0x96, 0xff, 0x12, 0x0c, 0x8e, 0x79, 0x92, 0xe7, //0x82f0,
    0xd3, 0x78, 0x95, 0x96, 0x40, 0x05, 0xe7, 0x96, 0xff, 0x80, 0x08, 0xc3, 0x79, 0x95, 0xe7, 0x78, //0x8300,
    0x92, 0x96, 0xff, 0x12, 0x0c, 0x8e, 0x12, 0x0c, 0x5b, 0x78, 0x8a, 0xe6, 0x25, 0xe0, 0x24, 0x4e, //0x8310,
    0xf8, 0xa6, 0x06, 0x08, 0xa6, 0x07, 0x78, 0x8a, 0xe6, 0x24, 0x6e, 0xf8, 0xa6, 0x09, 0x78, 0x8a, //0x8320,
    0xe6, 0x24, 0x01, 0xff, 0xe4, 0x33, 0xfe, 0xd3, 0xef, 0x94, 0x0f, 0xee, 0x64, 0x80, 0x94, 0x80, //0x8330,
    0x40, 0x04, 0x7f, 0x00, 0x80, 0x05, 0x78, 0x8a, 0xe6, 0x04, 0xff, 0x78, 0x8a, 0xa6, 0x07, 0xe5, //0x8340,
    0x1f, 0xb4, 0x01, 0x0a, 0xe6, 0x60, 0x03, 0x02, 0x04, 0xc0, 0x75, 0x1f, 0x02, 0x22, 0x12, 0x0c, //0x8350,
    0x7a, 0x78, 0x80, 0xa6, 0x06, 0x08, 0xa6, 0x07, 0x12, 0x0c, 0x7a, 0x78, 0x82, 0xa6, 0x06, 0x08, //0x8360,
    0xa6, 0x07, 0x78, 0x6e, 0xe6, 0x78, 0x8c, 0xf6, 0x78, 0x6e, 0xe6, 0x78, 0x8d, 0xf6, 0x7f, 0x01, //0x8370,
    0xef, 0x25, 0xe0, 0x24, 0x4f, 0xf9, 0xc3, 0x78, 0x81, 0xe6, 0x97, 0x18, 0xe6, 0x19, 0x97, 0x50, //0x8380,
    0x0a, 0x12, 0x0c, 0x82, 0x78, 0x80, 0xa6, 0x04, 0x08, 0xa6, 0x05, 0x74, 0x6e, 0x2f, 0xf9, 0x78, //0x8390,
    0x8c, 0xe6, 0xc3, 0x97, 0x50, 0x08, 0x74, 0x6e, 0x2f, 0xf8, 0xe6, 0x78, 0x8c, 0xf6, 0xef, 0x25, //0x83a0,
    0xe0, 0x24, 0x4f, 0xf9, 0xd3, 0x78, 0x83, 0xe6, 0x97, 0x18, 0xe6, 0x19, 0x97, 0x40, 0x0a, 0x12, //0x83b0,
    0x0c, 0x82, 0x78, 0x82, 0xa6, 0x04, 0x08, 0xa6, 0x05, 0x74, 0x6e, 0x2f, 0xf9, 0x78, 0x8d, 0xe6, //0x83c0,
    0xd3, 0x97, 0x40, 0x08, 0x74, 0x6e, 0x2f, 0xf8, 0xe6, 0x78, 0x8d, 0xf6, 0x0f, 0xef, 0x64, 0x10, //0x83d0,
    0x70, 0x9e, 0xc3, 0x79, 0x81, 0xe7, 0x78, 0x83, 0x96, 0xff, 0x19, 0xe7, 0x18, 0x96, 0x78, 0x84, //0x83e0,
    0xf6, 0x08, 0xa6, 0x07, 0xc3, 0x79, 0x8c, 0xe7, 0x78, 0x8d, 0x96, 0x08, 0xf6, 0xd3, 0x79, 0x81, //0x83f0,
    0xe7, 0x78, 0x7f, 0x96, 0x19, 0xe7, 0x18, 0x96, 0x40, 0x05, 0x09, 0xe7, 0x08, 0x80, 0x06, 0xc3, //0x8400,
    0x79, 0x7f, 0xe7, 0x78, 0x81, 0x96, 0xff, 0x19, 0xe7, 0x18, 0x96, 0xfe, 0x78, 0x86, 0xa6, 0x06, //0x8410,
    0x08, 0xa6, 0x07, 0x79, 0x8c, 0xe7, 0xd3, 0x78, 0x8b, 0x96, 0x40, 0x05, 0xe7, 0x96, 0xff, 0x80, //0x8420,
    0x08, 0xc3, 0x79, 0x8b, 0xe7, 0x78, 0x8c, 0x96, 0xff, 0x78, 0x8f, 0xa6, 0x07, 0xe5, 0x1f, 0x64, //0x8430,
    0x02, 0x70, 0x69, 0x90, 0x0e, 0x91, 0x93, 0xff, 0x18, 0xe6, 0xc3, 0x9f, 0x50, 0x72, 0x12, 0x0c, //0x8440,
    0x4a, 0x12, 0x0c, 0x2f, 0x90, 0x0e, 0x8e, 0x12, 0x0c, 0x38, 0x78, 0x80, 0x12, 0x0c, 0x6b, 0x7b, //0x8450,
    0x04, 0x12, 0x0c, 0x1d, 0xc3, 0x12, 0x06, 0x45, 0x50, 0x56, 0x90, 0x0e, 0x92, 0xe4, 0x93, 0xff, //0x8460,
    0x78, 0x8f, 0xe6, 0x9f, 0x40, 0x02, 0x80, 0x11, 0x90, 0x0e, 0x90, 0xe4, 0x93, 0xff, 0xd3, 0x78, //0x8470,
    0x89, 0xe6, 0x9f, 0x18, 0xe6, 0x94, 0x00, 0x40, 0x03, 0x75, 0x1f, 0x05, 0x12, 0x0c, 0x4a, 0x12, //0x8480,
    0x0c, 0x2f, 0x90, 0x0e, 0x8f, 0x12, 0x0c, 0x38, 0x78, 0x7e, 0x12, 0x0c, 0x6b, 0x7b, 0x40, 0x12, //0x8490,
    0x0c, 0x1d, 0xd3, 0x12, 0x06, 0x45, 0x40, 0x18, 0x75, 0x1f, 0x05, 0x22, 0xe5, 0x1f, 0xb4, 0x05, //0x84a0,
    0x0f, 0xd2, 0x01, 0xc2, 0x02, 0xe4, 0xf5, 0x1f, 0xf5, 0x1e, 0xd2, 0x35, 0xd2, 0x33, 0xd2, 0x36, //0x84b0,
    0x22, 0xef, 0x8d, 0xf0, 0xa4, 0xa8, 0xf0, 0xcf, 0x8c, 0xf0, 0xa4, 0x28, 0xce, 0x8d, 0xf0, 0xa4, //0x84c0,
    0x2e, 0xfe, 0x22, 0xbc, 0x00, 0x0b, 0xbe, 0x00, 0x29, 0xef, 0x8d, 0xf0, 0x84, 0xff, 0xad, 0xf0, //0x84d0,
    0x22, 0xe4, 0xcc, 0xf8, 0x75, 0xf0, 0x08, 0xef, 0x2f, 0xff, 0xee, 0x33, 0xfe, 0xec, 0x33, 0xfc, //0x84e0,
    0xee, 0x9d, 0xec, 0x98, 0x40, 0x05, 0xfc, 0xee, 0x9d, 0xfe, 0x0f, 0xd5, 0xf0, 0xe9, 0xe4, 0xce, //0x84f0,
    0xfd, 0x22, 0xed, 0xf8, 0xf5, 0xf0, 0xee, 0x84, 0x20, 0xd2, 0x1c, 0xfe, 0xad, 0xf0, 0x75, 0xf0, //0x8500,
    0x08, 0xef, 0x2f, 0xff, 0xed, 0x33, 0xfd, 0x40, 0x07, 0x98, 0x50, 0x06, 0xd5, 0xf0, 0xf2, 0x22, //0x8510,
    0xc3, 0x98, 0xfd, 0x0f, 0xd5, 0xf0, 0xea, 0x22, 0xe8, 0x8f, 0xf0, 0xa4, 0xcc, 0x8b, 0xf0, 0xa4, //0x8520,

    0x2c, 0xfc, 0xe9, 0x8e, 0xf0, 0xa4, 0x2c, 0xfc, 0x8a, 0xf0, 0xed, 0xa4, 0x2c, 0xfc, 0xea, 0x8e, //0x8530,
    0xf0, 0xa4, 0xcd, 0xa8, 0xf0, 0x8b, 0xf0, 0xa4, 0x2d, 0xcc, 0x38, 0x25, 0xf0, 0xfd, 0xe9, 0x8f, //0x8540,
    0xf0, 0xa4, 0x2c, 0xcd, 0x35, 0xf0, 0xfc, 0xeb, 0x8e, 0xf0, 0xa4, 0xfe, 0xa9, 0xf0, 0xeb, 0x8f, //0x8550,
    0xf0, 0xa4, 0xcf, 0xc5, 0xf0, 0x2e, 0xcd, 0x39, 0xfe, 0xe4, 0x3c, 0xfc, 0xea, 0xa4, 0x2d, 0xce, //0x8560,
    0x35, 0xf0, 0xfd, 0xe4, 0x3c, 0xfc, 0x22, 0x75, 0xf0, 0x08, 0x75, 0x82, 0x00, 0xef, 0x2f, 0xff, //0x8570,
    0xee, 0x33, 0xfe, 0xcd, 0x33, 0xcd, 0xcc, 0x33, 0xcc, 0xc5, 0x82, 0x33, 0xc5, 0x82, 0x9b, 0xed, //0x8580,
    0x9a, 0xec, 0x99, 0xe5, 0x82, 0x98, 0x40, 0x0c, 0xf5, 0x82, 0xee, 0x9b, 0xfe, 0xed, 0x9a, 0xfd, //0x8590,
    0xec, 0x99, 0xfc, 0x0f, 0xd5, 0xf0, 0xd6, 0xe4, 0xce, 0xfb, 0xe4, 0xcd, 0xfa, 0xe4, 0xcc, 0xf9, //0x85a0,
    0xa8, 0x82, 0x22, 0xb8, 0x00, 0xc1, 0xb9, 0x00, 0x59, 0xba, 0x00, 0x2d, 0xec, 0x8b, 0xf0, 0x84, //0x85b0,
    0xcf, 0xce, 0xcd, 0xfc, 0xe5, 0xf0, 0xcb, 0xf9, 0x78, 0x18, 0xef, 0x2f, 0xff, 0xee, 0x33, 0xfe, //0x85c0,
    0xed, 0x33, 0xfd, 0xec, 0x33, 0xfc, 0xeb, 0x33, 0xfb, 0x10, 0xd7, 0x03, 0x99, 0x40, 0x04, 0xeb, //0x85d0,
    0x99, 0xfb, 0x0f, 0xd8, 0xe5, 0xe4, 0xf9, 0xfa, 0x22, 0x78, 0x18, 0xef, 0x2f, 0xff, 0xee, 0x33, //0x85e0,
    0xfe, 0xed, 0x33, 0xfd, 0xec, 0x33, 0xfc, 0xc9, 0x33, 0xc9, 0x10, 0xd7, 0x05, 0x9b, 0xe9, 0x9a, //0x85f0,
    0x40, 0x07, 0xec, 0x9b, 0xfc, 0xe9, 0x9a, 0xf9, 0x0f, 0xd8, 0xe0, 0xe4, 0xc9, 0xfa, 0xe4, 0xcc, //0x8600,
    0xfb, 0x22, 0x75, 0xf0, 0x10, 0xef, 0x2f, 0xff, 0xee, 0x33, 0xfe, 0xed, 0x33, 0xfd, 0xcc, 0x33, //0x8610,
    0xcc, 0xc8, 0x33, 0xc8, 0x10, 0xd7, 0x07, 0x9b, 0xec, 0x9a, 0xe8, 0x99, 0x40, 0x0a, 0xed, 0x9b, //0x8620,
    0xfd, 0xec, 0x9a, 0xfc, 0xe8, 0x99, 0xf8, 0x0f, 0xd5, 0xf0, 0xda, 0xe4, 0xcd, 0xfb, 0xe4, 0xcc, //0x8630,
    0xfa, 0xe4, 0xc8, 0xf9, 0x22, 0xeb, 0x9f, 0xf5, 0xf0, 0xea, 0x9e, 0x42, 0xf0, 0xe9, 0x9d, 0x42, //0x8640,
    0xf0, 0xe8, 0x9c, 0x45, 0xf0, 0x22, 0xe8, 0x60, 0x0f, 0xec, 0xc3, 0x13, 0xfc, 0xed, 0x13, 0xfd, //0x8650,
    0xee, 0x13, 0xfe, 0xef, 0x13, 0xff, 0xd8, 0xf1, 0x22, 0xe8, 0x60, 0x0f, 0xef, 0xc3, 0x33, 0xff, //0x8660,
    0xee, 0x33, 0xfe, 0xed, 0x33, 0xfd, 0xec, 0x33, 0xfc, 0xd8, 0xf1, 0x22, 0xe4, 0x93, 0xfc, 0x74, //0x8670,
    0x01, 0x93, 0xfd, 0x74, 0x02, 0x93, 0xfe, 0x74, 0x03, 0x93, 0xff, 0x22, 0xe6, 0xfb, 0x08, 0xe6, //0x8680,
    0xf9, 0x08, 0xe6, 0xfa, 0x08, 0xe6, 0xcb, 0xf8, 0x22, 0xec, 0xf6, 0x08, 0xed, 0xf6, 0x08, 0xee, //0x8690,
    0xf6, 0x08, 0xef, 0xf6, 0x22, 0xa4, 0x25, 0x82, 0xf5, 0x82, 0xe5, 0xf0, 0x35, 0x83, 0xf5, 0x83, //0x86a0,
    0x22, 0xd0, 0x83, 0xd0, 0x82, 0xf8, 0xe4, 0x93, 0x70, 0x12, 0x74, 0x01, 0x93, 0x70, 0x0d, 0xa3, //0x86b0,
    0xa3, 0x93, 0xf8, 0x74, 0x01, 0x93, 0xf5, 0x82, 0x88, 0x83, 0xe4, 0x73, 0x74, 0x02, 0x93, 0x68, //0x86c0,
    0x60, 0xef, 0xa3, 0xa3, 0xa3, 0x80, 0xdf, 0x90, 0x38, 0x04, 0x78, 0x52, 0x12, 0x0b, 0xfd, 0x90, //0x86d0,
    0x38, 0x00, 0xe0, 0xfe, 0xa3, 0xe0, 0xfd, 0xed, 0xff, 0xc3, 0x12, 0x0b, 0x9e, 0x90, 0x38, 0x10, //0x86e0,
    0x12, 0x0b, 0x92, 0x90, 0x38, 0x06, 0x78, 0x54, 0x12, 0x0b, 0xfd, 0x90, 0x38, 0x02, 0xe0, 0xfe, //0x86f0,
    0xa3, 0xe0, 0xfd, 0xed, 0xff, 0xc3, 0x12, 0x0b, 0x9e, 0x90, 0x38, 0x12, 0x12, 0x0b, 0x92, 0xa3, //0x8700,
    0xe0, 0xb4, 0x31, 0x07, 0x78, 0x52, 0x79, 0x52, 0x12, 0x0c, 0x13, 0x90, 0x38, 0x14, 0xe0, 0xb4, //0x8710,
    0x71, 0x15, 0x78, 0x52, 0xe6, 0xfe, 0x08, 0xe6, 0x78, 0x02, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, //0x8720,
    0xf9, 0x79, 0x53, 0xf7, 0xee, 0x19, 0xf7, 0x90, 0x38, 0x15, 0xe0, 0xb4, 0x31, 0x07, 0x78, 0x54, //0x8730,
    0x79, 0x54, 0x12, 0x0c, 0x13, 0x90, 0x38, 0x15, 0xe0, 0xb4, 0x71, 0x15, 0x78, 0x54, 0xe6, 0xfe, //0x8740,
    0x08, 0xe6, 0x78, 0x02, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0x79, 0x55, 0xf7, 0xee, 0x19, //0x8750,
    0xf7, 0x79, 0x52, 0x12, 0x0b, 0xd9, 0x09, 0x12, 0x0b, 0xd9, 0xaf, 0x47, 0x12, 0x0b, 0xb2, 0xe5, //0x8760,
    0x44, 0xfb, 0x7a, 0x00, 0xfd, 0x7c, 0x00, 0x12, 0x04, 0xd3, 0x78, 0x5a, 0xa6, 0x06, 0x08, 0xa6, //0x8770,
    0x07, 0xaf, 0x45, 0x12, 0x0b, 0xb2, 0xad, 0x03, 0x7c, 0x00, 0x12, 0x04, 0xd3, 0x78, 0x56, 0xa6, //0x8780,
    0x06, 0x08, 0xa6, 0x07, 0xaf, 0x48, 0x78, 0x54, 0x12, 0x0b, 0xb4, 0xe5, 0x43, 0xfb, 0xfd, 0x7c, //0x8790,
    0x00, 0x12, 0x04, 0xd3, 0x78, 0x5c, 0xa6, 0x06, 0x08, 0xa6, 0x07, 0xaf, 0x46, 0x7e, 0x00, 0x78, //0x87a0,
    0x54, 0x12, 0x0b, 0xb6, 0xad, 0x03, 0x7c, 0x00, 0x12, 0x04, 0xd3, 0x78, 0x58, 0xa6, 0x06, 0x08, //0x87b0,
    0xa6, 0x07, 0xc3, 0x78, 0x5b, 0xe6, 0x94, 0x08, 0x18, 0xe6, 0x94, 0x00, 0x50, 0x05, 0x76, 0x00, //0x87c0,
    0x08, 0x76, 0x08, 0xc3, 0x78, 0x5d, 0xe6, 0x94, 0x08, 0x18, 0xe6, 0x94, 0x00, 0x50, 0x05, 0x76, //0x87d0,
    0x00, 0x08, 0x76, 0x08, 0x78, 0x5a, 0x12, 0x0b, 0xc6, 0xff, 0xd3, 0x78, 0x57, 0xe6, 0x9f, 0x18, //0x87e0,
    0xe6, 0x9e, 0x40, 0x0e, 0x78, 0x5a, 0xe6, 0x13, 0xfe, 0x08, 0xe6, 0x78, 0x57, 0x12, 0x0c, 0x08, //0x87f0,
    0x80, 0x04, 0x7e, 0x00, 0x7f, 0x00, 0x78, 0x5e, 0x12, 0x0b, 0xbe, 0xff, 0xd3, 0x78, 0x59, 0xe6, //0x8800,
    0x9f, 0x18, 0xe6, 0x9e, 0x40, 0x0e, 0x78, 0x5c, 0xe6, 0x13, 0xfe, 0x08, 0xe6, 0x78, 0x59, 0x12, //0x8810,
    0x0c, 0x08, 0x80, 0x04, 0x7e, 0x00, 0x7f, 0x00, 0xe4, 0xfc, 0xfd, 0x78, 0x62, 0x12, 0x06, 0x99, //0x8820,
    0x78, 0x5a, 0x12, 0x0b, 0xc6, 0x78, 0x57, 0x26, 0xff, 0xee, 0x18, 0x36, 0xfe, 0x78, 0x66, 0x12, //0x8830,
    0x0b, 0xbe, 0x78, 0x59, 0x26, 0xff, 0xee, 0x18, 0x36, 0xfe, 0xe4, 0xfc, 0xfd, 0x78, 0x6a, 0x12, //0x8840,
    0x06, 0x99, 0x12, 0x0b, 0xce, 0x78, 0x66, 0x12, 0x06, 0x8c, 0xd3, 0x12, 0x06, 0x45, 0x40, 0x08, //0x8850,
    0x12, 0x0b, 0xce, 0x78, 0x66, 0x12, 0x06, 0x99, 0x78, 0x54, 0x12, 0x0b, 0xd0, 0x78, 0x6a, 0x12, //0x8860,
    0x06, 0x8c, 0xd3, 0x12, 0x06, 0x45, 0x40, 0x0a, 0x78, 0x54, 0x12, 0x0b, 0xd0, 0x78, 0x6a, 0x12, //0x8870,
    0x06, 0x99, 0x78, 0x61, 0xe6, 0x90, 0x60, 0x01, 0xf0, 0x78, 0x65, 0xe6, 0xa3, 0xf0, 0x78, 0x69, //0x8880,
    0xe6, 0xa3, 0xf0, 0x78, 0x55, 0xe6, 0xa3, 0xf0, 0x7d, 0x01, 0x78, 0x61, 0x12, 0x0b, 0xe9, 0x24, //0x8890,
    0x01, 0x12, 0x0b, 0xa6, 0x78, 0x65, 0x12, 0x0b, 0xe9, 0x24, 0x02, 0x12, 0x0b, 0xa6, 0x78, 0x69, //0x88a0,
    0x12, 0x0b, 0xe9, 0x24, 0x03, 0x12, 0x0b, 0xa6, 0x78, 0x6d, 0x12, 0x0b, 0xe9, 0x24, 0x04, 0x12, //0x88b0,
    0x0b, 0xa6, 0x0d, 0xbd, 0x05, 0xd4, 0xc2, 0x0e, 0xc2, 0x06, 0x22, 0x85, 0x08, 0x41, 0x90, 0x30, //0x88c0,
    0x24, 0xe0, 0xf5, 0x3d, 0xa3, 0xe0, 0xf5, 0x3e, 0xa3, 0xe0, 0xf5, 0x3f, 0xa3, 0xe0, 0xf5, 0x40, //0x88d0,
    0xa3, 0xe0, 0xf5, 0x3c, 0xd2, 0x34, 0xe5, 0x41, 0x12, 0x06, 0xb1, 0x09, 0x31, 0x03, 0x09, 0x35, //0x88e0,
    0x04, 0x09, 0x3b, 0x05, 0x09, 0x3e, 0x06, 0x09, 0x41, 0x07, 0x09, 0x4a, 0x08, 0x09, 0x5b, 0x12, //0x88f0,
    0x09, 0x73, 0x18, 0x09, 0x89, 0x19, 0x09, 0x5e, 0x1a, 0x09, 0x6a, 0x1b, 0x09, 0xad, 0x80, 0x09, //0x8900,
    0xb2, 0x81, 0x0a, 0x1d, 0x8f, 0x0a, 0x09, 0x90, 0x0a, 0x1d, 0x91, 0x0a, 0x1d, 0x92, 0x0a, 0x1d, //0x8910,
    0x93, 0x0a, 0x1d, 0x94, 0x0a, 0x1d, 0x98, 0x0a, 0x17, 0x9f, 0x0a, 0x1a, 0xec, 0x00, 0x00, 0x0a, //0x8920,
    0x38, 0x12, 0x0f, 0x74, 0x22, 0x12, 0x0f, 0x74, 0xd2, 0x03, 0x22, 0xd2, 0x03, 0x22, 0xc2, 0x03, //0x8930,
    0x22, 0xa2, 0x37, 0xe4, 0x33, 0xf5, 0x3c, 0x02, 0x0a, 0x1d, 0xc2, 0x01, 0xc2, 0x02, 0xc2, 0x03, //0x8940,
    0x12, 0x0d, 0x0d, 0x75, 0x1e, 0x70, 0xd2, 0x35, 0x02, 0x0a, 0x1d, 0x02, 0x0a, 0x04, 0x85, 0x40, //0x8950,
    0x4a, 0x85, 0x3c, 0x4b, 0x12, 0x0a, 0xff, 0x02, 0x0a, 0x1d, 0x85, 0x4a, 0x40, 0x85, 0x4b, 0x3c, //0x8960,
    0x02, 0x0a, 0x1d, 0xe4, 0xf5, 0x22, 0xf5, 0x23, 0x85, 0x40, 0x31, 0x85, 0x3f, 0x30, 0x85, 0x3e, //0x8970,
    0x2f, 0x85, 0x3d, 0x2e, 0x12, 0x0f, 0x46, 0x80, 0x1f, 0x75, 0x22, 0x00, 0x75, 0x23, 0x01, 0x74, //0x8980,
    0xff, 0xf5, 0x2d, 0xf5, 0x2c, 0xf5, 0x2b, 0xf5, 0x2a, 0x12, 0x0f, 0x46, 0x85, 0x2d, 0x40, 0x85, //0x8990,
    0x2c, 0x3f, 0x85, 0x2b, 0x3e, 0x85, 0x2a, 0x3d, 0xe4, 0xf5, 0x3c, 0x80, 0x70, 0x12, 0x0f, 0x16, //0x89a0,
    0x80, 0x6b, 0x85, 0x3d, 0x45, 0x85, 0x3e, 0x46, 0xe5, 0x47, 0xc3, 0x13, 0xff, 0xe5, 0x45, 0xc3, //0x89b0,
    0x9f, 0x50, 0x02, 0x8f, 0x45, 0xe5, 0x48, 0xc3, 0x13, 0xff, 0xe5, 0x46, 0xc3, 0x9f, 0x50, 0x02, //0x89c0,
    0x8f, 0x46, 0xe5, 0x47, 0xc3, 0x13, 0xff, 0xfd, 0xe5, 0x45, 0x2d, 0xfd, 0xe4, 0x33, 0xfc, 0xe5, //0x89d0,
    0x44, 0x12, 0x0f, 0x90, 0x40, 0x05, 0xe5, 0x44, 0x9f, 0xf5, 0x45, 0xe5, 0x48, 0xc3, 0x13, 0xff, //0x89e0,
    0xfd, 0xe5, 0x46, 0x2d, 0xfd, 0xe4, 0x33, 0xfc, 0xe5, 0x43, 0x12, 0x0f, 0x90, 0x40, 0x05, 0xe5, //0x89f0,
    0x43, 0x9f, 0xf5, 0x46, 0x12, 0x06, 0xd7, 0x80, 0x14, 0x85, 0x40, 0x48, 0x85, 0x3f, 0x47, 0x85, //0x8a00,
    0x3e, 0x46, 0x85, 0x3d, 0x45, 0x80, 0x06, 0x02, 0x06, 0xd7, 0x12, 0x0d, 0x7e, 0x90, 0x30, 0x24, //0x8a10,
    0xe5, 0x3d, 0xf0, 0xa3, 0xe5, 0x3e, 0xf0, 0xa3, 0xe5, 0x3f, 0xf0, 0xa3, 0xe5, 0x40, 0xf0, 0xa3, //0x8a20,
    0xe5, 0x3c, 0xf0, 0x90, 0x30, 0x23, 0xe4, 0xf0, 0x22, 0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, //0x8a30,
    0xd0, 0x90, 0x3f, 0x0c, 0xe0, 0xf5, 0x32, 0xe5, 0x32, 0x30, 0xe3, 0x74, 0x30, 0x36, 0x66, 0x90, //0x8a40,
    0x60, 0x19, 0xe0, 0xf5, 0x0a, 0xa3, 0xe0, 0xf5, 0x0b, 0x90, 0x60, 0x1d, 0xe0, 0xf5, 0x14, 0xa3, //0x8a50,
    0xe0, 0xf5, 0x15, 0x90, 0x60, 0x21, 0xe0, 0xf5, 0x0c, 0xa3, 0xe0, 0xf5, 0x0d, 0x90, 0x60, 0x29, //0x8a60,
    0xe0, 0xf5, 0x0e, 0xa3, 0xe0, 0xf5, 0x0f, 0x90, 0x60, 0x31, 0xe0, 0xf5, 0x10, 0xa3, 0xe0, 0xf5, //0x8a70,
    0x11, 0x90, 0x60, 0x39, 0xe0, 0xf5, 0x12, 0xa3, 0xe0, 0xf5, 0x13, 0x30, 0x01, 0x06, 0x30, 0x33, //0x8a80,
    0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0x09, 0x30, 0x02, 0x06, 0x30, 0x33, 0x03, 0xd3, 0x80, 0x01, //0x8a90,
    0xc3, 0x92, 0x0a, 0x30, 0x33, 0x0c, 0x30, 0x03, 0x09, 0x20, 0x02, 0x06, 0x20, 0x01, 0x03, 0xd3, //0x8aa0,
    0x80, 0x01, 0xc3, 0x92, 0x0b, 0x90, 0x30, 0x01, 0xe0, 0x44, 0x40, 0xf0, 0xe0, 0x54, 0xbf, 0xf0, //0x8ab0,
    0xe5, 0x32, 0x30, 0xe1, 0x14, 0x30, 0x34, 0x11, 0x90, 0x30, 0x22, 0xe0, 0xf5, 0x08, 0xe4, 0xf0, //0x8ac0,
    0x30, 0x00, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0x08, 0xe5, 0x32, 0x30, 0xe5, 0x12, 0x90, 0x56, //0x8ad0,
    0xa1, 0xe0, 0xf5, 0x09, 0x30, 0x31, 0x09, 0x30, 0x05, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0x0d, //0x8ae0,
    0x90, 0x3f, 0x0c, 0xe5, 0x32, 0xf0, 0xd0, 0xd0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32, 0x90, //0x8af0,
    0x0e, 0x7e, 0xe4, 0x93, 0xfe, 0x74, 0x01, 0x93, 0xff, 0xc3, 0x90, 0x0e, 0x7c, 0x74, 0x01, 0x93, //0x8b00,
    0x9f, 0xff, 0xe4, 0x93, 0x9e, 0xfe, 0xe4, 0x8f, 0x3b, 0x8e, 0x3a, 0xf5, 0x39, 0xf5, 0x38, 0xab, //0x8b10,
    0x3b, 0xaa, 0x3a, 0xa9, 0x39, 0xa8, 0x38, 0xaf, 0x4b, 0xfc, 0xfd, 0xfe, 0x12, 0x05, 0x28, 0x12, //0x8b20,
    0x0d, 0xe1, 0xe4, 0x7b, 0xff, 0xfa, 0xf9, 0xf8, 0x12, 0x05, 0xb3, 0x12, 0x0d, 0xe1, 0x90, 0x0e, //0x8b30,
    0x69, 0xe4, 0x12, 0x0d, 0xf6, 0x12, 0x0d, 0xe1, 0xe4, 0x85, 0x4a, 0x37, 0xf5, 0x36, 0xf5, 0x35, //0x8b40,
    0xf5, 0x34, 0xaf, 0x37, 0xae, 0x36, 0xad, 0x35, 0xac, 0x34, 0xa3, 0x12, 0x0d, 0xf6, 0x8f, 0x37, //0x8b50,
    0x8e, 0x36, 0x8d, 0x35, 0x8c, 0x34, 0xe5, 0x3b, 0x45, 0x37, 0xf5, 0x3b, 0xe5, 0x3a, 0x45, 0x36, //0x8b60,
    0xf5, 0x3a, 0xe5, 0x39, 0x45, 0x35, 0xf5, 0x39, 0xe5, 0x38, 0x45, 0x34, 0xf5, 0x38, 0xe4, 0xf5, //0x8b70,
    0x22, 0xf5, 0x23, 0x85, 0x3b, 0x31, 0x85, 0x3a, 0x30, 0x85, 0x39, 0x2f, 0x85, 0x38, 0x2e, 0x02, //0x8b80,
    0x0f, 0x46, 0xe0, 0xa3, 0xe0, 0x75, 0xf0, 0x02, 0xa4, 0xff, 0xae, 0xf0, 0xc3, 0x08, 0xe6, 0x9f, //0x8b90,
    0xf6, 0x18, 0xe6, 0x9e, 0xf6, 0x22, 0xff, 0xe5, 0xf0, 0x34, 0x60, 0x8f, 0x82, 0xf5, 0x83, 0xec, //0x8ba0,
    0xf0, 0x22, 0x78, 0x52, 0x7e, 0x00, 0xe6, 0xfc, 0x08, 0xe6, 0xfd, 0x02, 0x04, 0xc1, 0xe4, 0xfc, //0x8bb0,
    0xfd, 0x12, 0x06, 0x99, 0x78, 0x5c, 0xe6, 0xc3, 0x13, 0xfe, 0x08, 0xe6, 0x13, 0x22, 0x78, 0x52, //0x8bc0,
    0xe6, 0xfe, 0x08, 0xe6, 0xff, 0xe4, 0xfc, 0xfd, 0x22, 0xe7, 0xc4, 0xf8, 0x54, 0xf0, 0xc8, 0x68, //0x8bd0,
    0xf7, 0x09, 0xe7, 0xc4, 0x54, 0x0f, 0x48, 0xf7, 0x22, 0xe6, 0xfc, 0xed, 0x75, 0xf0, 0x04, 0xa4, //0x8be0,
    0x22, 0x12, 0x06, 0x7c, 0x8f, 0x48, 0x8e, 0x47, 0x8d, 0x46, 0x8c, 0x45, 0x22, 0xe0, 0xfe, 0xa3, //0x8bf0,
    0xe0, 0xfd, 0xee, 0xf6, 0xed, 0x08, 0xf6, 0x22, 0x13, 0xff, 0xc3, 0xe6, 0x9f, 0xff, 0x18, 0xe6, //0x8c00,
    0x9e, 0xfe, 0x22, 0xe6, 0xc3, 0x13, 0xf7, 0x08, 0xe6, 0x13, 0x09, 0xf7, 0x22, 0xad, 0x39, 0xac, //0x8c10,
    0x38, 0xfa, 0xf9, 0xf8, 0x12, 0x05, 0x28, 0x8f, 0x3b, 0x8e, 0x3a, 0x8d, 0x39, 0x8c, 0x38, 0xab, //0x8c20,
    0x37, 0xaa, 0x36, 0xa9, 0x35, 0xa8, 0x34, 0x22, 0x93, 0xff, 0xe4, 0xfc, 0xfd, 0xfe, 0x12, 0x05, //0x8c30,
    0x28, 0x8f, 0x37, 0x8e, 0x36, 0x8d, 0x35, 0x8c, 0x34, 0x22, 0x78, 0x84, 0xe6, 0xfe, 0x08, 0xe6, //0x8c40,
    0xff, 0xe4, 0x8f, 0x37, 0x8e, 0x36, 0xf5, 0x35, 0xf5, 0x34, 0x22, 0x90, 0x0e, 0x8c, 0xe4, 0x93, //0x8c50,
    0x25, 0xe0, 0x24, 0x0a, 0xf8, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x22, 0xe6, 0xfe, 0x08, 0xe6, 0xff, //0x8c60,
    0xe4, 0x8f, 0x3b, 0x8e, 0x3a, 0xf5, 0x39, 0xf5, 0x38, 0x22, 0x78, 0x4e, 0xe6, 0xfe, 0x08, 0xe6, //0x8c70,
    0xff, 0x22, 0xef, 0x25, 0xe0, 0x24, 0x4e, 0xf8, 0xe6, 0xfc, 0x08, 0xe6, 0xfd, 0x22, 0x78, 0x89, //0x8c80,
    0xef, 0x26, 0xf6, 0x18, 0xe4, 0x36, 0xf6, 0x22, 0x75, 0x89, 0x03, 0x75, 0xa8, 0x01, 0x75, 0xb8, //0x8c90,
    0x04, 0x75, 0x34, 0xff, 0x75, 0x35, 0x0e, 0x75, 0x36, 0x15, 0x75, 0x37, 0x0d, 0x12, 0x0e, 0x9a, //0x8ca0,
    0x12, 0x00, 0x09, 0x12, 0x0f, 0x16, 0x12, 0x00, 0x06, 0xd2, 0x00, 0xd2, 0x34, 0xd2, 0xaf, 0x75, //0x8cb0,
    0x34, 0xff, 0x75, 0x35, 0x0e, 0x75, 0x36, 0x49, 0x75, 0x37, 0x03, 0x12, 0x0e, 0x9a, 0x30, 0x08, //0x8cc0,
    0x09, 0xc2, 0x34, 0x12, 0x08, 0xcb, 0xc2, 0x08, 0xd2, 0x34, 0x30, 0x0b, 0x09, 0xc2, 0x36, 0x12, //0x8cd0,
    0x02, 0x6c, 0xc2, 0x0b, 0xd2, 0x36, 0x30, 0x09, 0x09, 0xc2, 0x36, 0x12, 0x00, 0x0e, 0xc2, 0x09, //0x8ce0,
    0xd2, 0x36, 0x30, 0x0e, 0x03, 0x12, 0x06, 0xd7, 0x30, 0x35, 0xd3, 0x90, 0x30, 0x29, 0xe5, 0x1e, //0x8cf0,
    0xf0, 0xb4, 0x10, 0x05, 0x90, 0x30, 0x23, 0xe4, 0xf0, 0xc2, 0x35, 0x80, 0xc1, 0xe4, 0xf5, 0x4b, //0x8d00,
    0x90, 0x0e, 0x7a, 0x93, 0xff, 0xe4, 0x8f, 0x37, 0xf5, 0x36, 0xf5, 0x35, 0xf5, 0x34, 0xaf, 0x37, //0x8d10,
    0xae, 0x36, 0xad, 0x35, 0xac, 0x34, 0x90, 0x0e, 0x6a, 0x12, 0x0d, 0xf6, 0x8f, 0x37, 0x8e, 0x36, //0x8d20,
    0x8d, 0x35, 0x8c, 0x34, 0x90, 0x0e, 0x72, 0x12, 0x06, 0x7c, 0xef, 0x45, 0x37, 0xf5, 0x37, 0xee, //0x8d30,
    0x45, 0x36, 0xf5, 0x36, 0xed, 0x45, 0x35, 0xf5, 0x35, 0xec, 0x45, 0x34, 0xf5, 0x34, 0xe4, 0xf5, //0x8d40,
    0x22, 0xf5, 0x23, 0x85, 0x37, 0x31, 0x85, 0x36, 0x30, 0x85, 0x35, 0x2f, 0x85, 0x34, 0x2e, 0x12, //0x8d50,
    0x0f, 0x46, 0xe4, 0xf5, 0x22, 0xf5, 0x23, 0x90, 0x0e, 0x72, 0x12, 0x0d, 0xea, 0x12, 0x0f, 0x46, //0x8d60,
    0xe4, 0xf5, 0x22, 0xf5, 0x23, 0x90, 0x0e, 0x6e, 0x12, 0x0d, 0xea, 0x02, 0x0f, 0x46, 0xe5, 0x40, //0x8d70,
    0x24, 0xf2, 0xf5, 0x37, 0xe5, 0x3f, 0x34, 0x43, 0xf5, 0x36, 0xe5, 0x3e, 0x34, 0xa2, 0xf5, 0x35, //0x8d80,
    0xe5, 0x3d, 0x34, 0x28, 0xf5, 0x34, 0xe5, 0x37, 0xff, 0xe4, 0xfe, 0xfd, 0xfc, 0x78, 0x18, 0x12, //0x8d90,
    0x06, 0x69, 0x8f, 0x40, 0x8e, 0x3f, 0x8d, 0x3e, 0x8c, 0x3d, 0xe5, 0x37, 0x54, 0xa0, 0xff, 0xe5, //0x8da0,
    0x36, 0xfe, 0xe4, 0xfd, 0xfc, 0x78, 0x07, 0x12, 0x06, 0x56, 0x78, 0x10, 0x12, 0x0f, 0x9a, 0xe4, //0x8db0,
    0xff, 0xfe, 0xe5, 0x35, 0xfd, 0xe4, 0xfc, 0x78, 0x0e, 0x12, 0x06, 0x56, 0x12, 0x0f, 0x9d, 0xe4, //0x8dc0,
    0xff, 0xfe, 0xfd, 0xe5, 0x34, 0xfc, 0x78, 0x18, 0x12, 0x06, 0x56, 0x78, 0x08, 0x12, 0x0f, 0x9a, //0x8dd0,
    0x22, 0x8f, 0x3b, 0x8e, 0x3a, 0x8d, 0x39, 0x8c, 0x38, 0x22, 0x12, 0x06, 0x7c, 0x8f, 0x31, 0x8e, //0x8de0,
    0x30, 0x8d, 0x2f, 0x8c, 0x2e, 0x22, 0x93, 0xf9, 0xf8, 0x02, 0x06, 0x69, 0x00, 0x00, 0x00, 0x00, //0x8df0,
    0x12, 0x01, 0x17, 0x08, 0x31, 0x15, 0x53, 0x54, 0x44, 0x20, 0x20, 0x20, 0x20, 0x20, 0x13, 0x01, //0x8e00,
    0x10, 0x01, 0x56, 0x40, 0x1a, 0x30, 0x29, 0x7e, 0x00, 0x30, 0x04, 0x20, 0xdf, 0x30, 0x05, 0x40, //0x8e10,
    0xbf, 0x50, 0x03, 0x00, 0xfd, 0x50, 0x27, 0x01, 0xfe, 0x60, 0x00, 0x11, 0x00, 0x3f, 0x05, 0x30, //0x8e20,
    0x00, 0x3f, 0x06, 0x22, 0x00, 0x3f, 0x01, 0x2a, 0x00, 0x3f, 0x02, 0x00, 0x00, 0x36, 0x06, 0x07, //0x8e30,
    0x00, 0x3f, 0x0b, 0x0f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x30, 0x01, 0x40, 0xbf, 0x30, 0x01, 0x00, //0x8e40,
    0xbf, 0x30, 0x29, 0x70, 0x00, 0x3a, 0x00, 0x00, 0xff, 0x3a, 0x00, 0x00, 0xff, 0x36, 0x03, 0x36, //0x8e50,
    0x02, 0x41, 0x44, 0x58, 0x20, 0x18, 0x10, 0x0a, 0x04, 0x04, 0x00, 0x03, 0xff, 0x64, 0x00, 0x00, //0x8e60,
    0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x04, 0x06, 0x06, 0x00, 0x03, 0x51, 0x00, 0x7a, //0x8e70,
    0x50, 0x3c, 0x28, 0x1e, 0x10, 0x10, 0x50, 0x2d, 0x28, 0x16, 0x10, 0x10, 0x02, 0x00, 0x10, 0x0c, //0x8e80,
    0x10, 0x04, 0x0c, 0x6e, 0x06, 0x05, 0x00, 0xa5, 0x5a, 0x00, 0xae, 0x35, 0xaf, 0x36, 0xe4, 0xfd, //0x8e90,
    0xed, 0xc3, 0x95, 0x37, 0x50, 0x33, 0x12, 0x0f, 0xe2, 0xe4, 0x93, 0xf5, 0x38, 0x74, 0x01, 0x93, //0x8ea0,
    0xf5, 0x39, 0x45, 0x38, 0x60, 0x23, 0x85, 0x39, 0x82, 0x85, 0x38, 0x83, 0xe0, 0xfc, 0x12, 0x0f, //0x8eb0,
    0xe2, 0x74, 0x03, 0x93, 0x52, 0x04, 0x12, 0x0f, 0xe2, 0x74, 0x02, 0x93, 0x42, 0x04, 0x85, 0x39, //0x8ec0,
    0x82, 0x85, 0x38, 0x83, 0xec, 0xf0, 0x0d, 0x80, 0xc7, 0x22, 0x78, 0xbe, 0xe6, 0xd3, 0x08, 0xff, //0x8ed0,
    0xe6, 0x64, 0x80, 0xf8, 0xef, 0x64, 0x80, 0x98, 0x22, 0x93, 0xff, 0x7e, 0x00, 0xe6, 0xfc, 0x08, //0x8ee0,
    0xe6, 0xfd, 0x12, 0x04, 0xc1, 0x78, 0xc1, 0xe6, 0xfc, 0x08, 0xe6, 0xfd, 0xd3, 0xef, 0x9d, 0xee, //0x8ef0,
    0x9c, 0x22, 0x78, 0xbd, 0xd3, 0xe6, 0x64, 0x80, 0x94, 0x80, 0x22, 0x25, 0xe0, 0x24, 0x0a, 0xf8, //0x8f00,
    0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x22, 0xe5, 0x3c, 0xd3, 0x94, 0x00, 0x40, 0x0b, 0x90, 0x0e, 0x88, //0x8f10,
    0x12, 0x0b, 0xf1, 0x90, 0x0e, 0x86, 0x80, 0x09, 0x90, 0x0e, 0x82, 0x12, 0x0b, 0xf1, 0x90, 0x0e, //0x8f20,
    0x80, 0xe4, 0x93, 0xf5, 0x44, 0xa3, 0xe4, 0x93, 0xf5, 0x43, 0xd2, 0x06, 0x30, 0x06, 0x03, 0xd3, //0x8f30,
    0x80, 0x01, 0xc3, 0x92, 0x0e, 0x22, 0xa2, 0xaf, 0x92, 0x32, 0xc2, 0xaf, 0xe5, 0x23, 0x45, 0x22, //0x8f40,
    0x90, 0x0e, 0x5d, 0x60, 0x0e, 0x12, 0x0f, 0xcb, 0xe0, 0xf5, 0x2c, 0x12, 0x0f, 0xc8, 0xe0, 0xf5, //0x8f50,
    0x2d, 0x80, 0x0c, 0x12, 0x0f, 0xcb, 0xe5, 0x30, 0xf0, 0x12, 0x0f, 0xc8, 0xe5, 0x31, 0xf0, 0xa2, //0x8f60,
    0x32, 0x92, 0xaf, 0x22, 0xd2, 0x01, 0xc2, 0x02, 0xe4, 0xf5, 0x1f, 0xf5, 0x1e, 0xd2, 0x35, 0xd2, //0x8f70,
    0x33, 0xd2, 0x36, 0xd2, 0x01, 0xc2, 0x02, 0xf5, 0x1f, 0xf5, 0x1e, 0xd2, 0x35, 0xd2, 0x33, 0x22, //0x8f80,
    0xfb, 0xd3, 0xed, 0x9b, 0x74, 0x80, 0xf8, 0x6c, 0x98, 0x22, 0x12, 0x06, 0x69, 0xe5, 0x40, 0x2f, //0x8f90,
    0xf5, 0x40, 0xe5, 0x3f, 0x3e, 0xf5, 0x3f, 0xe5, 0x3e, 0x3d, 0xf5, 0x3e, 0xe5, 0x3d, 0x3c, 0xf5, //0x8fa0,
    0x3d, 0x22, 0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x90, 0x3f, 0x0d, 0xe0, 0xf5, 0x33, 0xe5, 0x33, //0x8fb0,
    0xf0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32, 0x90, 0x0e, 0x5f, 0xe4, 0x93, 0xfe, 0x74, 0x01, //0x8fc0,
    0x93, 0xf5, 0x82, 0x8e, 0x83, 0x22, 0x78, 0x7f, 0xe4, 0xf6, 0xd8, 0xfd, 0x75, 0x81, 0xcd, 0x02, //0x8fd0,
    0x0c, 0x98, 0x8f, 0x82, 0x8e, 0x83, 0x75, 0xf0, 0x04, 0xed, 0x02, 0x06, 0xa5,                   //0x8fe0

};

#define SENSORDB(fmt, arg...)  printk(fmt, ##arg)
static struct timeval OV5640YUV_ktv1, OV5640YUV_ktv2;
struct i2c_client * g_client=NULL;

#define UINT32  unsigned int
#define  UINT8  u8

typedef enum
{
    OV5640_720P,       //1M 1280x960
    OV5640_5M,     //5M 2592x1944
} OV5640_RES_TYPE;
OV5640_RES_TYPE OV5640YUV_g_RES=OV5640_720P;

typedef enum
{
    OV5640_MODE_PREVIEW,  //1M  	1280x960
    OV5640_MODE_CAPTURE   //5M    2592x1944
} OV5640_MODE;


OV5640_MODE g_iOV5640YUV_Mode=OV5640_MODE_PREVIEW;


#define KAL_FALSE false
#define KAL_TRUE  true
#define kal_uint32  unsigned int
#define kal_uint16  u16
#define kal_uint8  unsigned char
#define UINT16  u16
#define UINT8   unsigned char
#define  kal_bool  bool
#define Sleep   msleep

UINT8 OV5640YUVPixelClockDivider=0;
kal_uint32 OV5640YUV_sensor_pclk=56000000;
kal_uint32 OV5640YUV_PV_pclk = 5600;
kal_uint32 OV5640YUV_CAP_pclk = 5600;
kal_uint16 OV5640YUV_pv_exposure_lines=0x100,OV5640YUV_g_iBackupExtraExp = 0,OV5640YUV_extra_exposure_lines = 0;
kal_uint16 OV5640YUV_sensor_id=0;
//MSDK_SENSOR_CONFIG_STRUCT OV5640YUVSensorConfigData;
kal_uint32 OV5640YUV_FAC_SENSOR_REG;
kal_uint16 OV5640YUV_sensor_flip_value;


//liuxinming add
kal_uint32 back_shutter = 0;
kal_uint32 back_pv_gain = 0;
kal_uint32 tem = 0;



bool  OV5640YUV_MPEG4_encode_mode = KAL_FALSE;
bool  OV5640YUV_night_mode = KAL_FALSE;

#define  ERROR_NONE  1


inline void OV5640YUV_imgSensorProfileStart(void)
{
    do_gettimeofday(&OV5640YUV_ktv1);
}

inline void OV5640YUV_imgSensorProfileEnd(char *tag)
{
    unsigned long TimeIntervalUS;
    do_gettimeofday(&OV5640YUV_ktv2);

    TimeIntervalUS = (OV5640YUV_ktv2.tv_sec - OV5640YUV_ktv1.tv_sec) * 1000000 + (OV5640YUV_ktv2.tv_usec - OV5640YUV_ktv1.tv_usec);
    SENSORDB("[%s]Profile = %lu\n",tag, TimeIntervalUS);
}


u8  OV5640YUV_read_cmos_sensor(u16 addr)
{
    unsigned char value=0;

     i2cc_get_reg(g_client,addr,&value);

     return value;
}

void OV5640YUV_write_cmos_sensor(u16 addr,u32 param)
{
      i2cc_set_reg(g_client,addr,param);
}



static void OV5640_FOCUS_AD5820_Check_MCU()
{
    u8 check[13] = {0x00};
    //mcu on
    check[0] = OV5640YUV_read_cmos_sensor(0x3000);
    check[1] = OV5640YUV_read_cmos_sensor(0x3004);
    //soft reset of mcu
    check[2] = OV5640YUV_read_cmos_sensor(0x3f00);
    //afc on
    check[3] = OV5640YUV_read_cmos_sensor(0x3001);
    check[4] = OV5640YUV_read_cmos_sensor(0x3005);
    //gpio1,gpio2
    check[5] = OV5640YUV_read_cmos_sensor(0x3018);
    check[6] = OV5640YUV_read_cmos_sensor(0x301e);
    check[7] = OV5640YUV_read_cmos_sensor(0x301b);
    check[8] = OV5640YUV_read_cmos_sensor(0x3042);
    //y0
    check[9] = OV5640YUV_read_cmos_sensor(0x3018);
    check[10] = OV5640YUV_read_cmos_sensor(0x301e);
    check[11] = OV5640YUV_read_cmos_sensor(0x301b);
    check[12] = OV5640YUV_read_cmos_sensor(0x3042);

    int i = 0;
    for(i = 0; i < 13; i++)
        SENSORDB("check[%d]=0x%x\n", i, check[i]);
}





static void OV5640_FOCUS_AD5820_Init(void)
{
    u8 state=0x8F;
    unsigned int  iteration = 100;
    int totalCnt = 0;
    int sentCnt = 0;
    int index=0;
    u16 addr = 0x8000;
    u8 buf[256];
    int len = 128;


  //  OV5640YUV_imgSensorProfileStart();
    OV5640YUV_write_cmos_sensor(0x3000, 0x20);
    totalCnt = ARRAY_SIZE(AD5820_Config);

#if 0//Brust mode
    while (index < totalCnt) {
        sentCnt = totalCnt - index > len  ? len  : totalCnt - index;
        buf[0] = addr >> 8;
        buf[1] = addr & 0xff;
        memcpy(&buf[2], &AD5820_Config[index], len );
        OV5640YUV_multi_write_cmos_sensor(buf, sentCnt + 2);
        addr += len ;
        index += len ;
    }
#else//single mode
    for(sentCnt =0; sentCnt<totalCnt; sentCnt++)
    {
        OV5640YUV_write_cmos_sensor(addr,AD5820_Config[sentCnt]);
        addr++;
    }
#endif
    mdelay(10);
    OV5640YUV_write_cmos_sensor(0x3022, 0x00);
    OV5640YUV_write_cmos_sensor(0x3023, 0x00);
    OV5640YUV_write_cmos_sensor(0x3024, 0x00);
    OV5640YUV_write_cmos_sensor(0x3025, 0x00);
    OV5640YUV_write_cmos_sensor(0x3026, 0x00);
    OV5640YUV_write_cmos_sensor(0x3027, 0x00);
    OV5640YUV_write_cmos_sensor(0x3028, 0x00);
    OV5640YUV_write_cmos_sensor(0x3029, 0x7f);
    OV5640YUV_write_cmos_sensor(0x3000, 0x00);

    do {
        state = (u8)OV5640YUV_read_cmos_sensor(0x3029);

        mdelay(5);
        if (iteration-- == 0)
        {
            break;
        }
    } while(state!=0x70);

    OV5640YUV_imgSensorProfileEnd("OV5640_FOCUS_AD5820_Init");
    OV5640_FOCUS_AD5820_Check_MCU();
    return;
}   /*  OV5640_FOCUS_AD5820_Init  */

void OV5640YUV_Sensor_Dvp_Init(void)
{
    OV5640YUV_write_cmos_sensor(0x4740, 0x20);//liuxinming

    OV5640YUV_write_cmos_sensor(0x3008, 0x42);
    OV5640YUV_write_cmos_sensor(0x3103, 0x03);
    OV5640YUV_write_cmos_sensor(0x3017, 0x7f);
    OV5640YUV_write_cmos_sensor(0x3018, 0xff);
    OV5640YUV_write_cmos_sensor(0x302c, 0x82);
    OV5640YUV_write_cmos_sensor(0x3108, 0x01);
    OV5640YUV_write_cmos_sensor(0x3630, 0x2e);//2e
    OV5640YUV_write_cmos_sensor(0x3632, 0xe2);
    OV5640YUV_write_cmos_sensor(0x3633, 0x23);//23
    OV5640YUV_write_cmos_sensor(0x3621, 0xe0);
    OV5640YUV_write_cmos_sensor(0x3704, 0xa0);
    OV5640YUV_write_cmos_sensor(0x3703, 0x5a);
    OV5640YUV_write_cmos_sensor(0x3715, 0x78);
    OV5640YUV_write_cmos_sensor(0x3717, 0x01);
    OV5640YUV_write_cmos_sensor(0x370b, 0x60);
    OV5640YUV_write_cmos_sensor(0x3705, 0x1a);
    OV5640YUV_write_cmos_sensor(0x3905, 0x02);
    OV5640YUV_write_cmos_sensor(0x3906, 0x10);
    OV5640YUV_write_cmos_sensor(0x3901, 0x0a);
    OV5640YUV_write_cmos_sensor(0x3731, 0x12);
    OV5640YUV_write_cmos_sensor(0x3600, 0x08);
    OV5640YUV_write_cmos_sensor(0x3601, 0x33);
    OV5640YUV_write_cmos_sensor(0x302d, 0x60);
    OV5640YUV_write_cmos_sensor(0x3620, 0x52);
    OV5640YUV_write_cmos_sensor(0x371b, 0x20);
    OV5640YUV_write_cmos_sensor(0x471c, 0x50);

    OV5640YUV_write_cmos_sensor(0x3a18, 0x00);
    OV5640YUV_write_cmos_sensor(0x3a19, 0xf8);

    OV5640YUV_write_cmos_sensor(0x3635, 0x1c);//1c
    OV5640YUV_write_cmos_sensor(0x3634, 0x40);
    OV5640YUV_write_cmos_sensor(0x3622, 0x01);

    OV5640YUV_write_cmos_sensor(0x3c04, 0x28);
    OV5640YUV_write_cmos_sensor(0x3c05, 0x98);
    OV5640YUV_write_cmos_sensor(0x3c06, 0x00);
    OV5640YUV_write_cmos_sensor(0x3c07, 0x08);
    OV5640YUV_write_cmos_sensor(0x3c08, 0x00);
    OV5640YUV_write_cmos_sensor(0x3c09, 0x1c);
    OV5640YUV_write_cmos_sensor(0x3c0a, 0x9c);
    OV5640YUV_write_cmos_sensor(0x3c0b, 0x40);

  //  OV5640YUV_write_cmos_sensor(0x3820, 0x47);
   // OV5640YUV_write_cmos_sensor(0x3821, 0x01);

    //dg add 2015-07-24 for stop flip & mirror image
    OV5640YUV_write_cmos_sensor(0x3820, 0x40);
    OV5640YUV_write_cmos_sensor(0x3821, 0x06);

    //windows setup
    OV5640YUV_write_cmos_sensor(0x3800, 0x00);
    OV5640YUV_write_cmos_sensor(0x3801, 0x00);
    OV5640YUV_write_cmos_sensor(0x3802, 0x00);
    OV5640YUV_write_cmos_sensor(0x3803, 0x04);

    //dg add  2015-07-25 to adjust X_AADR_END long for image windeos show
    OV5640YUV_write_cmos_sensor(0x3804, 0x0a);
    OV5640YUV_write_cmos_sensor(0x3805, 0x5f); //3f-5f->Good


    OV5640YUV_write_cmos_sensor(0x3806, 0x07);
    OV5640YUV_write_cmos_sensor(0x3807, 0x9b);
#if 1
    OV5640YUV_write_cmos_sensor(0x3808, 0x05);//1280
    OV5640YUV_write_cmos_sensor(0x3809, 0x00);

    OV5640YUV_write_cmos_sensor(0x380a, 0x03);//960
    OV5640YUV_write_cmos_sensor(0x380b, 0xc0);
#else
    OV5640YUV_write_cmos_sensor(0x3808, 0x05);
    OV5640YUV_write_cmos_sensor(0x3809, 0x80);
    OV5640YUV_write_cmos_sensor(0x380a, 0x01);
    OV5640YUV_write_cmos_sensor(0x380b, 0xe0);

#endif



    //OV5640YUV_write_cmos_sensor(0x3810, 0x00);
   // OV5640YUV_write_cmos_sensor(0x3811, 0x10);

    //dg add  2015-07-25 to adjust X OFFSET position coordinate for image windeos show
    OV5640YUV_write_cmos_sensor(0x3810, 0x00); // 00->01->00
    OV5640YUV_write_cmos_sensor(0x3811, 0xED); // 10->00->F0->EF->EE->ED->Good

    OV5640YUV_write_cmos_sensor(0x3812, 0x00);
    OV5640YUV_write_cmos_sensor(0x3813, 0x06);
    OV5640YUV_write_cmos_sensor(0x3814, 0x31);
    OV5640YUV_write_cmos_sensor(0x3815, 0x31);


    OV5640YUV_write_cmos_sensor(0x3034, 0x1a);
    OV5640YUV_write_cmos_sensor(0x3035, 0x21); //15fps
    OV5640YUV_write_cmos_sensor(0x3036, 0x46);
    OV5640YUV_write_cmos_sensor(0x3037, 0x13);
    OV5640YUV_write_cmos_sensor(0x3038, 0x00);
    OV5640YUV_write_cmos_sensor(0x3039, 0x00);

    OV5640YUV_write_cmos_sensor(0x380c, 0x07);
    OV5640YUV_write_cmos_sensor(0x380d, 0x68);
    OV5640YUV_write_cmos_sensor(0x380e, 0x03); //03
    OV5640YUV_write_cmos_sensor(0x380f, 0xd8); //d8

    OV5640YUV_write_cmos_sensor(0x3c01, 0xb4);
    OV5640YUV_write_cmos_sensor(0x3c00, 0x04);
    OV5640YUV_write_cmos_sensor(0x3a08, 0x00);
    OV5640YUV_write_cmos_sensor(0x3a09, 0x93);
    OV5640YUV_write_cmos_sensor(0x3a0e, 0x06);
    OV5640YUV_write_cmos_sensor(0x3a0a, 0x00);
    OV5640YUV_write_cmos_sensor(0x3a0b, 0x7b);
    OV5640YUV_write_cmos_sensor(0x3a0d, 0x08);

    OV5640YUV_write_cmos_sensor(0x3a00, 0x38); //25fps-20fps
    OV5640YUV_write_cmos_sensor(0x3a02, 0x03);
    OV5640YUV_write_cmos_sensor(0x3a03, 0xd8);
    OV5640YUV_write_cmos_sensor(0x3a14, 0x03);
    OV5640YUV_write_cmos_sensor(0x3a15, 0xd8);

    OV5640YUV_write_cmos_sensor(0x3618, 0x00);
    OV5640YUV_write_cmos_sensor(0x3612, 0x29);
    OV5640YUV_write_cmos_sensor(0x3708, 0x64);
    OV5640YUV_write_cmos_sensor(0x3709, 0x52);
    OV5640YUV_write_cmos_sensor(0x370c, 0x03);

    OV5640YUV_write_cmos_sensor(0x4001, 0x02);
    OV5640YUV_write_cmos_sensor(0x4004, 0x02);
    OV5640YUV_write_cmos_sensor(0x3000, 0x00);
    OV5640YUV_write_cmos_sensor(0x3002, 0x1c);
    OV5640YUV_write_cmos_sensor(0x3004, 0xff);
    OV5640YUV_write_cmos_sensor(0x3006, 0xc3);
    OV5640YUV_write_cmos_sensor(0x300e, 0x58);
    OV5640YUV_write_cmos_sensor(0x302e, 0x00);

     //OV5640YUV_write_cmos_sensor(0x4300, 0x30);
     OV5640YUV_write_cmos_sensor(0x4300, 0x32); //dg changge from 0x30->0x33

    OV5640YUV_write_cmos_sensor(0x501f, 0x00);
    OV5640YUV_write_cmos_sensor(0x4713, 0x03);
    OV5640YUV_write_cmos_sensor(0x4407, 0x04);
    OV5640YUV_write_cmos_sensor(0x460b, 0x35);
    OV5640YUV_write_cmos_sensor(0x460c, 0x22);//add by bright
    OV5640YUV_write_cmos_sensor(0x3824, 0x01);//add by bright
    OV5640YUV_write_cmos_sensor(0x5001, 0xa3);

    OV5640YUV_write_cmos_sensor(0x3406, 0x01);//awbinit
    OV5640YUV_write_cmos_sensor(0x3400, 0x06);
    OV5640YUV_write_cmos_sensor(0x3401, 0x80);
    OV5640YUV_write_cmos_sensor(0x3402, 0x04);
    OV5640YUV_write_cmos_sensor(0x3403, 0x00);
    OV5640YUV_write_cmos_sensor(0x3404, 0x06);
    OV5640YUV_write_cmos_sensor(0x3405, 0x00);
    //awb
    OV5640YUV_write_cmos_sensor(0x5180, 0xff);
    OV5640YUV_write_cmos_sensor(0x5181, 0xf2);
    OV5640YUV_write_cmos_sensor(0x5182, 0x00);
    OV5640YUV_write_cmos_sensor(0x5183, 0x14);
    OV5640YUV_write_cmos_sensor(0x5184, 0x25);
    OV5640YUV_write_cmos_sensor(0x5185, 0x24);
    OV5640YUV_write_cmos_sensor(0x5186, 0x16);
    OV5640YUV_write_cmos_sensor(0x5187, 0x16);
    OV5640YUV_write_cmos_sensor(0x5188, 0x16);
    OV5640YUV_write_cmos_sensor(0x5189, 0x72);
    OV5640YUV_write_cmos_sensor(0x518a, 0x68);
    OV5640YUV_write_cmos_sensor(0x518b, 0xf0);
    OV5640YUV_write_cmos_sensor(0x518c, 0xb2);
    OV5640YUV_write_cmos_sensor(0x518d, 0x50);
    OV5640YUV_write_cmos_sensor(0x518e, 0x30);
    OV5640YUV_write_cmos_sensor(0x518f, 0x30);
    OV5640YUV_write_cmos_sensor(0x5190, 0x50);
    OV5640YUV_write_cmos_sensor(0x5191, 0xf8);
    OV5640YUV_write_cmos_sensor(0x5192, 0x04);
    OV5640YUV_write_cmos_sensor(0x5193, 0x70);
    OV5640YUV_write_cmos_sensor(0x5194, 0xf0);
    OV5640YUV_write_cmos_sensor(0x5195, 0xf0);
    OV5640YUV_write_cmos_sensor(0x5196, 0x03);
    OV5640YUV_write_cmos_sensor(0x5197, 0x01);
    OV5640YUV_write_cmos_sensor(0x5198, 0x04);
    OV5640YUV_write_cmos_sensor(0x5199, 0x12);
    OV5640YUV_write_cmos_sensor(0x519a, 0x04);
    OV5640YUV_write_cmos_sensor(0x519b, 0x00);
    OV5640YUV_write_cmos_sensor(0x519c, 0x06);
    OV5640YUV_write_cmos_sensor(0x519d, 0x82);
    OV5640YUV_write_cmos_sensor(0x519e, 0x38);
    //color matrix
    OV5640YUV_write_cmos_sensor(0x5381, 0x1e);
    OV5640YUV_write_cmos_sensor(0x5382, 0x5b);
    OV5640YUV_write_cmos_sensor(0x5383, 0x14);
    OV5640YUV_write_cmos_sensor(0x5384, 0x06);
    OV5640YUV_write_cmos_sensor(0x5385, 0x82);
    OV5640YUV_write_cmos_sensor(0x5386, 0x88);
    OV5640YUV_write_cmos_sensor(0x5387, 0x7c);
    OV5640YUV_write_cmos_sensor(0x5388, 0x60);
    OV5640YUV_write_cmos_sensor(0x5389, 0x1c);
    OV5640YUV_write_cmos_sensor(0x538a, 0x01);
    OV5640YUV_write_cmos_sensor(0x538b, 0x98);
    //sharp&noise
    OV5640YUV_write_cmos_sensor(0x5300, 0x08);
    OV5640YUV_write_cmos_sensor(0x5301, 0x30);
    OV5640YUV_write_cmos_sensor(0x5302, 0x3f);
    OV5640YUV_write_cmos_sensor(0x5303, 0x10);
    OV5640YUV_write_cmos_sensor(0x5304, 0x08);
    OV5640YUV_write_cmos_sensor(0x5305, 0x30);
    OV5640YUV_write_cmos_sensor(0x5306, 0x18);
    OV5640YUV_write_cmos_sensor(0x5307, 0x28);
    OV5640YUV_write_cmos_sensor(0x5309, 0x08);
    OV5640YUV_write_cmos_sensor(0x530a, 0x30);
    OV5640YUV_write_cmos_sensor(0x530b, 0x04);
    OV5640YUV_write_cmos_sensor(0x530c, 0x06);
    //gamma
    OV5640YUV_write_cmos_sensor(0x5480, 0x01);
    OV5640YUV_write_cmos_sensor(0x5481, 0x06);
    OV5640YUV_write_cmos_sensor(0x5482, 0x12);
    OV5640YUV_write_cmos_sensor(0x5483, 0x1e);
    OV5640YUV_write_cmos_sensor(0x5484, 0x4a);
    OV5640YUV_write_cmos_sensor(0x5485, 0x58);
    OV5640YUV_write_cmos_sensor(0x5486, 0x65);
    OV5640YUV_write_cmos_sensor(0x5487, 0x72);
    OV5640YUV_write_cmos_sensor(0x5488, 0x7d);
    OV5640YUV_write_cmos_sensor(0x5489, 0x88);
    OV5640YUV_write_cmos_sensor(0x548a, 0x92);
    OV5640YUV_write_cmos_sensor(0x548b, 0xa3);
    OV5640YUV_write_cmos_sensor(0x548c, 0xb2);
    OV5640YUV_write_cmos_sensor(0x548d, 0xc8);
    OV5640YUV_write_cmos_sensor(0x548e, 0xdd);
    OV5640YUV_write_cmos_sensor(0x548f, 0xf0);
    OV5640YUV_write_cmos_sensor(0x5490, 0x15);
    //UV adjust
    OV5640YUV_write_cmos_sensor(0x5580, 0x06);
    OV5640YUV_write_cmos_sensor(0x5583, 0x40);
    OV5640YUV_write_cmos_sensor(0x5584, 0x10);
    OV5640YUV_write_cmos_sensor(0x5589, 0x10);
    OV5640YUV_write_cmos_sensor(0x558a, 0x00);
    OV5640YUV_write_cmos_sensor(0x558b, 0xf8);
    //lens shading
    OV5640YUV_write_cmos_sensor(0x5000, 0xa7);
    OV5640YUV_write_cmos_sensor(0x5800, 0x20);
    OV5640YUV_write_cmos_sensor(0x5801, 0x19);
    OV5640YUV_write_cmos_sensor(0x5802, 0x17);
    OV5640YUV_write_cmos_sensor(0x5803, 0x16);
    OV5640YUV_write_cmos_sensor(0x5804, 0x18);
    OV5640YUV_write_cmos_sensor(0x5805, 0x21);
    OV5640YUV_write_cmos_sensor(0x5806, 0x0F);
    OV5640YUV_write_cmos_sensor(0x5807, 0x0A);
    OV5640YUV_write_cmos_sensor(0x5808, 0x07);
    OV5640YUV_write_cmos_sensor(0x5809, 0x07);
    OV5640YUV_write_cmos_sensor(0x580a, 0x0A);
    OV5640YUV_write_cmos_sensor(0x580b, 0x0C);
    OV5640YUV_write_cmos_sensor(0x580c, 0x0A);
    OV5640YUV_write_cmos_sensor(0x580d, 0x03);
    OV5640YUV_write_cmos_sensor(0x580e, 0x01);
    OV5640YUV_write_cmos_sensor(0x580f, 0x01);
    OV5640YUV_write_cmos_sensor(0x5810, 0x03);
    OV5640YUV_write_cmos_sensor(0x5811, 0x09);
    OV5640YUV_write_cmos_sensor(0x5812, 0x0A);
    OV5640YUV_write_cmos_sensor(0x5813, 0x03);
    OV5640YUV_write_cmos_sensor(0x5814, 0x01);
    OV5640YUV_write_cmos_sensor(0x5815, 0x01);
    OV5640YUV_write_cmos_sensor(0x5816, 0x03);
    OV5640YUV_write_cmos_sensor(0x5817, 0x08);
    OV5640YUV_write_cmos_sensor(0x5818, 0x10);
    OV5640YUV_write_cmos_sensor(0x5819, 0x0A);
    OV5640YUV_write_cmos_sensor(0x581a, 0x06);
    OV5640YUV_write_cmos_sensor(0x581b, 0x06);
    OV5640YUV_write_cmos_sensor(0x581c, 0x08);
    OV5640YUV_write_cmos_sensor(0x581d, 0x0E);
    OV5640YUV_write_cmos_sensor(0x581e, 0x22);
    OV5640YUV_write_cmos_sensor(0x581f, 0x18);
    OV5640YUV_write_cmos_sensor(0x5820, 0x13);
    OV5640YUV_write_cmos_sensor(0x5821, 0x12);
    OV5640YUV_write_cmos_sensor(0x5822, 0x16);
    OV5640YUV_write_cmos_sensor(0x5823, 0x1E);
    OV5640YUV_write_cmos_sensor(0x5824, 0x64);
    OV5640YUV_write_cmos_sensor(0x5825, 0x2A);
    OV5640YUV_write_cmos_sensor(0x5826, 0x2C);
    OV5640YUV_write_cmos_sensor(0x5827, 0x2A);
    OV5640YUV_write_cmos_sensor(0x5828, 0x46);
    OV5640YUV_write_cmos_sensor(0x5829, 0x2A);
    OV5640YUV_write_cmos_sensor(0x582a, 0x26);
    OV5640YUV_write_cmos_sensor(0x582b, 0x24);
    OV5640YUV_write_cmos_sensor(0x582c, 0x26);
    OV5640YUV_write_cmos_sensor(0x582d, 0x2A);
    OV5640YUV_write_cmos_sensor(0x582e, 0x28);
    OV5640YUV_write_cmos_sensor(0x582f, 0x42);
    OV5640YUV_write_cmos_sensor(0x5830, 0x40);
    OV5640YUV_write_cmos_sensor(0x5831, 0x42);
    OV5640YUV_write_cmos_sensor(0x5832, 0x08);
    OV5640YUV_write_cmos_sensor(0x5833, 0x28);
    OV5640YUV_write_cmos_sensor(0x5834, 0x26);
    OV5640YUV_write_cmos_sensor(0x5835, 0x24);
    OV5640YUV_write_cmos_sensor(0x5836, 0x26);
    OV5640YUV_write_cmos_sensor(0x5837, 0x2A);
    OV5640YUV_write_cmos_sensor(0x5838, 0x44);
    OV5640YUV_write_cmos_sensor(0x5839, 0x4A);
    OV5640YUV_write_cmos_sensor(0x583a, 0x2C);
    OV5640YUV_write_cmos_sensor(0x583b, 0x2a);
    OV5640YUV_write_cmos_sensor(0x583c, 0x46);
    OV5640YUV_write_cmos_sensor(0x583d, 0xCE);

    OV5640YUV_write_cmos_sensor(0x5688, 0x22);
    OV5640YUV_write_cmos_sensor(0x5689, 0x22);
    OV5640YUV_write_cmos_sensor(0x568a, 0x42);
    OV5640YUV_write_cmos_sensor(0x568b, 0x24);
    OV5640YUV_write_cmos_sensor(0x568c, 0x42);
    OV5640YUV_write_cmos_sensor(0x568d, 0x24);
    OV5640YUV_write_cmos_sensor(0x568e, 0x22);
    OV5640YUV_write_cmos_sensor(0x568f, 0x22);

    OV5640YUV_write_cmos_sensor(0x5025, 0x00);

    OV5640YUV_write_cmos_sensor(0x3a0f, 0x30);
    OV5640YUV_write_cmos_sensor(0x3a10, 0x28);
    OV5640YUV_write_cmos_sensor(0x3a1b, 0x30);
    OV5640YUV_write_cmos_sensor(0x3a1e, 0x28);
    OV5640YUV_write_cmos_sensor(0x3a11, 0x61);
    OV5640YUV_write_cmos_sensor(0x3a1f, 0x10);

    OV5640YUV_write_cmos_sensor(0x4005, 0x1a);
    OV5640YUV_write_cmos_sensor(0x3406, 0x00);//awbinit
    OV5640YUV_write_cmos_sensor(0x3503, 0x00);//awbinit
    OV5640YUV_write_cmos_sensor(0x3008, 0x02);
}


//set constant focus
static void OV5640_FOCUS_AD5820_Constant_Focus(void)
{
    UINT8 state = 0x8F;
    UINT32 iteration = 300;

    //send constant focus mode command to firmware
    OV5640YUV_write_cmos_sensor(0x3023,0x01);
    OV5640YUV_write_cmos_sensor(0x3022,0x04);
    return;
}


static void OV5640_FOCUS_AD5820_Single_Focus()
{

    UINT8 state = 0x8F;
    UINT32 iteration = 100;
    OV5640YUV_write_cmos_sensor(0x3023,0x01);
    OV5640YUV_write_cmos_sensor(0x3022,0x03);

    iteration = 100;
    do{
        state = (UINT8)OV5640YUV_read_cmos_sensor(0x3023);

        if(state == 0x00)
        {
            SENSORDB("single focused!\n");
            break;
        }
     //   mdelay(30);

         mdelay(3);

        iteration --;

    }while(iteration);

    return;
}

static void OV5640_FOCUS_AD5820_Pause_Focus()
{
    UINT8 state = 0x8F;
    UINT32 iteration = 100;

    //send idle command to firmware
    OV5640YUV_write_cmos_sensor(0x3023,0x01);
    OV5640YUV_write_cmos_sensor(0x3022,0x06);

    iteration = 100;
    do{
        state = (UINT8)OV5640YUV_read_cmos_sensor(0x3023);

        if(state == 0x00)
        {
            break;
        }
        msleep(30);
    //      msleep(10);

        iteration --;

    }while(iteration);

    if(iteration==0)
    {
        printk("pause focus fail.........state is 0x%x...",state);

       return ;

    }

    printk("pause focus  OK ......");

}
static void OV5640_FOCUS_AD5820_Cancel_Focus()
{

    UINT8 state = 0x8F;
    UINT32 iteration = 100;

    //send idle command to firmware
    OV5640YUV_write_cmos_sensor(0x3023,0x01);
    OV5640YUV_write_cmos_sensor(0x3022,0x08);

    iteration = 100;
    do{
        state = (UINT8)OV5640YUV_read_cmos_sensor(0x3023);
        if(state == 0x00)
        {
            break;
        }
        msleep(30);
        iteration --;

    }while(iteration);

}

void OV5640YUV_set_720P_init(void)
{
    //OV5640YUV_write_cmos_sensor(0x3008, 0x42);

    OV5640YUV_write_cmos_sensor(0x5189, 0x72);

    OV5640YUV_write_cmos_sensor(0x3503, 0x00);//AE
    //OV5640YUV_write_cmos_sensor(0x3406, 0x00);//AWB
    OV5640YUV_write_cmos_sensor(0x3a00, 0x38);//enable night

    OV5640YUV_write_cmos_sensor(0x5302, 0x20);
    OV5640YUV_write_cmos_sensor(0x5303, 0x08);
    OV5640YUV_write_cmos_sensor(0x5306, 0x10);//18
    OV5640YUV_write_cmos_sensor(0x5307, 0x20);//28

    //OV5640YUV_write_cmos_sensor(0x3820, 0x47);
   // OV5640YUV_write_cmos_sensor(0x3821, 0x01);

    //dg add 2015-07-24 for stop flip image
    OV5640YUV_write_cmos_sensor(0x3820, 0x40);
    OV5640YUV_write_cmos_sensor(0x3821, 0x06);

    OV5640YUV_write_cmos_sensor(0x3108, 0x01);


    //windows setup
    OV5640YUV_write_cmos_sensor(0x3800, 0x00);
    OV5640YUV_write_cmos_sensor(0x3801, 0x00);
    OV5640YUV_write_cmos_sensor(0x3802, 0x00);
    OV5640YUV_write_cmos_sensor(0x3803, 0x04);

    //dg add  2015-07-25 to adjust X_AADR_END long for image windeos show
    OV5640YUV_write_cmos_sensor(0x3804, 0x0a);
    OV5640YUV_write_cmos_sensor(0x3805, 0x5f); //3f-5f->Good


    OV5640YUV_write_cmos_sensor(0x3806, 0x07);
    OV5640YUV_write_cmos_sensor(0x3807, 0x9b);
#if 1
    OV5640YUV_write_cmos_sensor(0x3808, 0x05);//1280
    OV5640YUV_write_cmos_sensor(0x3809, 0x00);

    OV5640YUV_write_cmos_sensor(0x380a, 0x03);//960
    OV5640YUV_write_cmos_sensor(0x380b, 0xc0);
#else
    OV5640YUV_write_cmos_sensor(0x3808, 0x05);
    OV5640YUV_write_cmos_sensor(0x3809, 0x80);
    OV5640YUV_write_cmos_sensor(0x380a, 0x01);
    OV5640YUV_write_cmos_sensor(0x380b, 0xe0);

#endif



    //OV5640YUV_write_cmos_sensor(0x3810, 0x00);
   // OV5640YUV_write_cmos_sensor(0x3811, 0x10);

    //dg add  2015-07-25 to adjust X OFFSET position coordinate for image windeos show
    OV5640YUV_write_cmos_sensor(0x3810, 0x00); // 00->01->00
    OV5640YUV_write_cmos_sensor(0x3811, 0xED); // 10->00->F0->EF->EE->ED->Good

    OV5640YUV_write_cmos_sensor(0x3812, 0x00);
    OV5640YUV_write_cmos_sensor(0x3813, 0x06);
    OV5640YUV_write_cmos_sensor(0x3814, 0x31);
    OV5640YUV_write_cmos_sensor(0x3815, 0x31);




    OV5640YUV_write_cmos_sensor(0x3034, 0x1a);
    OV5640YUV_write_cmos_sensor(0x3035, 0x21); //25fps
    OV5640YUV_write_cmos_sensor(0x3036, 0x46);
    OV5640YUV_write_cmos_sensor(0x3037, 0x13);
    OV5640YUV_write_cmos_sensor(0x3038, 0x00);
    OV5640YUV_write_cmos_sensor(0x3039, 0x00);

    OV5640YUV_write_cmos_sensor(0x380c, 0x07);
    OV5640YUV_write_cmos_sensor(0x380d, 0x68);
    OV5640YUV_write_cmos_sensor(0x380e, 0x03);
    OV5640YUV_write_cmos_sensor(0x380f, 0xd8);

    OV5640YUV_write_cmos_sensor(0x3a08, 0x00);
    OV5640YUV_write_cmos_sensor(0x3a09, 0x93);
    OV5640YUV_write_cmos_sensor(0x3a0e, 0x06);
    OV5640YUV_write_cmos_sensor(0x3a0a, 0x00);
    OV5640YUV_write_cmos_sensor(0x3a0b, 0x7b);
    OV5640YUV_write_cmos_sensor(0x3a0d, 0x08);

    OV5640YUV_write_cmos_sensor(0x3618, 0x00);
    OV5640YUV_write_cmos_sensor(0x3612, 0x29);
    OV5640YUV_write_cmos_sensor(0x3709, 0x52);
    OV5640YUV_write_cmos_sensor(0x370c, 0x03);

    OV5640YUV_write_cmos_sensor(0x4004, 0x02);
    OV5640YUV_write_cmos_sensor(0x460b, 0x35);
    OV5640YUV_write_cmos_sensor(0x460c, 0x22);
    OV5640YUV_write_cmos_sensor(0x4837, 0x15);
    OV5640YUV_write_cmos_sensor(0x3824, 0x01);
    OV5640YUV_write_cmos_sensor(0x5001, 0xa3);

    //OV5640YUV_write_cmos_sensor(0x3008, 0x02);
}

void OV5640YUV_set_5M_init(void)
{
    //OV5640YUV_write_cmos_sensor(0x3008, 0x42);

    OV5640YUV_write_cmos_sensor(0x5189, 0x66);

    OV5640YUV_write_cmos_sensor(0x3503, 0x07);//AE
    //OV5640YUV_write_cmos_sensor(0x3406, 0x01);//AWB
    OV5640YUV_write_cmos_sensor(0x3a00, 0x38);//disable night

    OV5640YUV_write_cmos_sensor(0x5302, 0x30);
    OV5640YUV_write_cmos_sensor(0x5303, 0x10);
    OV5640YUV_write_cmos_sensor(0x5306, 0x08);
    OV5640YUV_write_cmos_sensor(0x5307, 0x18);

    OV5640YUV_write_cmos_sensor(0x3820, 0x40); //46
    OV5640YUV_write_cmos_sensor(0x3821, 0x06); //00

    OV5640YUV_write_cmos_sensor(0x3800, 0x00);
    OV5640YUV_write_cmos_sensor(0x3801, 0x00);
    OV5640YUV_write_cmos_sensor(0x3802, 0x00);
    OV5640YUV_write_cmos_sensor(0x3803, 0x00);
    OV5640YUV_write_cmos_sensor(0x3804, 0x0a);
    OV5640YUV_write_cmos_sensor(0x3805, 0x3f);
    OV5640YUV_write_cmos_sensor(0x3806, 0x07);
    OV5640YUV_write_cmos_sensor(0x3807, 0x9f);
    OV5640YUV_write_cmos_sensor(0x3808, 0x0a);
    OV5640YUV_write_cmos_sensor(0x3809, 0x20);
    OV5640YUV_write_cmos_sensor(0x380a, 0x07);
    OV5640YUV_write_cmos_sensor(0x380b, 0x98);
    OV5640YUV_write_cmos_sensor(0x3810, 0x00);
    OV5640YUV_write_cmos_sensor(0x3811, 0x10);
    OV5640YUV_write_cmos_sensor(0x3812, 0x00);
    OV5640YUV_write_cmos_sensor(0x3813, 0x04);
    OV5640YUV_write_cmos_sensor(0x3814, 0x11);
    OV5640YUV_write_cmos_sensor(0x3815, 0x11);

    OV5640YUV_write_cmos_sensor(0x3034, 0x1a);
    OV5640YUV_write_cmos_sensor(0x3035, 0x11); //10fps
    OV5640YUV_write_cmos_sensor(0x3036, 0x46);
    OV5640YUV_write_cmos_sensor(0x3037, 0x13);
    OV5640YUV_write_cmos_sensor(0x3038, 0x00);
    OV5640YUV_write_cmos_sensor(0x3039, 0x00);

    OV5640YUV_write_cmos_sensor(0x380c, 0x0b);
    OV5640YUV_write_cmos_sensor(0x380d, 0x1c);
    OV5640YUV_write_cmos_sensor(0x380e, 0x07);
    OV5640YUV_write_cmos_sensor(0x380f, 0xb0);

    OV5640YUV_write_cmos_sensor(0x3a08, 0x00);
    OV5640YUV_write_cmos_sensor(0x3a09, 0xc5);
    OV5640YUV_write_cmos_sensor(0x3a0e, 0x0a);
    OV5640YUV_write_cmos_sensor(0x3a0a, 0x00);
    OV5640YUV_write_cmos_sensor(0x3a0b, 0xa4);
    OV5640YUV_write_cmos_sensor(0x3a0d, 0x0c);

    OV5640YUV_write_cmos_sensor(0x3618, 0x04);
    OV5640YUV_write_cmos_sensor(0x3612, 0x2b);
    OV5640YUV_write_cmos_sensor(0x3709, 0x12);
    OV5640YUV_write_cmos_sensor(0x370c, 0x00);

    OV5640YUV_write_cmos_sensor(0x4004, 0x06);
    OV5640YUV_write_cmos_sensor(0x3002, 0x00);
    OV5640YUV_write_cmos_sensor(0x3006, 0xff);
    OV5640YUV_write_cmos_sensor(0x4713, 0x02);
    OV5640YUV_write_cmos_sensor(0x4407, 0x04);
    OV5640YUV_write_cmos_sensor(0x460b, 0x37);
    OV5640YUV_write_cmos_sensor(0x460c, 0x22);
    OV5640YUV_write_cmos_sensor(0x4837, 0x16);
    OV5640YUV_write_cmos_sensor(0x3824, 0x01);
    OV5640YUV_write_cmos_sensor(0x5001, 0x83);

    //OV5640YUV_write_cmos_sensor(0x3008, 0x02);
    mdelay(300);//liuxinming
}


void OV5640YUV_set_720P(void)
{
    SENSORDB("OV5640YUV_set_720P Start \n");
    OV5640YUV_g_RES = OV5640_720P;
    OV5640YUV_set_720P_init();
    OV5640YUV_PV_pclk = 5600;
    OV5640YUV_sensor_pclk=56000000;
    SENSORDB("Set 720P End\n");
}


void OV5640YUV_set_5M(void)
{
    SENSORDB("Set 5M begin\n");
    OV5640YUV_g_RES = OV5640_5M;
    OV5640YUV_set_5M_init();
    OV5640YUV_CAP_pclk = 5600;
    OV5640YUV_sensor_pclk=56000000;
    SENSORDB("Set 5M End\n");
}


/*************************************************************************
* FUNCTION
*   OV5640_night_mode
*
* DESCRIPTION
*   This function night mode of OV5640.
*
* PARAMETERS
*   none
*
* RETURNS
*   None
*
* GLOBALS AFFECTED
*
*************************************************************************/
void OV5640YUV_NightMode(bool bEnable)
{
    if(bEnable)
    {
        OV5640YUV_night_mode = true;

        if(OV5640YUV_MPEG4_encode_mode== true)
        {
            OV5640YUV_write_cmos_sensor(0x3034, 0x1a);
            OV5640YUV_write_cmos_sensor(0x3035, 0x21); //10fps
            OV5640YUV_write_cmos_sensor(0x3036, 0x46);
            OV5640YUV_write_cmos_sensor(0x3037, 0x13);
            OV5640YUV_write_cmos_sensor(0x3038, 0x00);
            OV5640YUV_write_cmos_sensor(0x3039, 0x00);

            OV5640YUV_write_cmos_sensor(0x380c, 0x07);
            OV5640YUV_write_cmos_sensor(0x380d, 0x68);
            OV5640YUV_write_cmos_sensor(0x380e, 0x05);
            OV5640YUV_write_cmos_sensor(0x380f, 0xc4);

            OV5640YUV_write_cmos_sensor(0x3c01, 0xb4);
            OV5640YUV_write_cmos_sensor(0x3c00, 0x04);
            OV5640YUV_write_cmos_sensor(0x3a08, 0x00);
            OV5640YUV_write_cmos_sensor(0x3a09, 0x93);
            OV5640YUV_write_cmos_sensor(0x3a0e, 0x0a);
            OV5640YUV_write_cmos_sensor(0x3a0a, 0x00);
            OV5640YUV_write_cmos_sensor(0x3a0b, 0x7b);
            OV5640YUV_write_cmos_sensor(0x3a0d, 0x0c);

            OV5640YUV_write_cmos_sensor(0x3a00, 0x38);
            OV5640YUV_write_cmos_sensor(0x3a02 ,0x05);
            OV5640YUV_write_cmos_sensor(0x3a03 ,0xc4);
            OV5640YUV_write_cmos_sensor(0x3a14 ,0x05);
            OV5640YUV_write_cmos_sensor(0x3a15 ,0xc4);



        }
        else
        {
            OV5640YUV_write_cmos_sensor(0x3a00, 0x3c);//25fps-5fps
            OV5640YUV_write_cmos_sensor(0x3a02 ,0x0b);
            OV5640YUV_write_cmos_sensor(0x3a03 ,0x88);
            OV5640YUV_write_cmos_sensor(0x3a14 ,0x0b);
            OV5640YUV_write_cmos_sensor(0x3a15 ,0x88);
        }
    }
    else
    {
        OV5640YUV_night_mode = false;

        if(OV5640YUV_MPEG4_encode_mode==false)
        {
            OV5640YUV_write_cmos_sensor(0x3034, 0x1a);
            OV5640YUV_write_cmos_sensor(0x3035, 0x21); //15fps
            OV5640YUV_write_cmos_sensor(0x3036, 0x46);
            OV5640YUV_write_cmos_sensor(0x3037, 0x13);
            OV5640YUV_write_cmos_sensor(0x3038, 0x00);
            OV5640YUV_write_cmos_sensor(0x3039, 0x00);

            OV5640YUV_write_cmos_sensor(0x380c, 0x07);
            OV5640YUV_write_cmos_sensor(0x380d, 0x68);
            OV5640YUV_write_cmos_sensor(0x380e, 0x03);
            OV5640YUV_write_cmos_sensor(0x380f, 0xd8);

            OV5640YUV_write_cmos_sensor(0x3c01, 0xb4);
            OV5640YUV_write_cmos_sensor(0x3c00, 0x04);
            OV5640YUV_write_cmos_sensor(0x3a08, 0x00);
            OV5640YUV_write_cmos_sensor(0x3a09, 0x93);
            OV5640YUV_write_cmos_sensor(0x3a0e, 0x06);
            OV5640YUV_write_cmos_sensor(0x3a0a, 0x00);
            OV5640YUV_write_cmos_sensor(0x3a0b, 0x7b);
            OV5640YUV_write_cmos_sensor(0x3a0d, 0x08);

            OV5640YUV_write_cmos_sensor(0x3a00, 0x38);
            OV5640YUV_write_cmos_sensor(0x3a02 ,0x03);
            OV5640YUV_write_cmos_sensor(0x3a03 ,0xd8);
            OV5640YUV_write_cmos_sensor(0x3a14 ,0x03);
            OV5640YUV_write_cmos_sensor(0x3a15 ,0xd8);
        }
        else
        {
            OV5640YUV_write_cmos_sensor(0x3a00, 0x38);//25fps-20fps
            OV5640YUV_write_cmos_sensor(0x3a02 ,0x03);
            OV5640YUV_write_cmos_sensor(0x3a03 ,0xd8);
            OV5640YUV_write_cmos_sensor(0x3a14 ,0x03);
            OV5640YUV_write_cmos_sensor(0x3a15 ,0xd8);
        }
    }
}

static void OV5640YUV_SetDummy(const kal_uint16 iPixels, const kal_uint16 iLines)
{
   return ;
}


static void OV5640YUV_set_AE_mode(kal_bool AE_enable)
{
    kal_uint8 temp_AE_reg = 0;

    if (AE_enable == KAL_TRUE)
    {
        OV5640YUV_write_cmos_sensor(0x3503, 0x00);
    }
    else
    {
        OV5640YUV_write_cmos_sensor(0x3503, 0x07);
    }
}

#if 0
static void OV5640YUV_set_AWB_mode(kal_bool AWB_enable)
{
    kal_uint8 temp_AWB_reg = 0;

    if (AWB_enable == KAL_TRUE)
    {
        OV5640YUV_write_cmos_sensor(0x3406, 0x00);
    }
    else
    {
        OV5640YUV_write_cmos_sensor(0x3406, 0x01);
    }
}
#endif
/*************************************************************************
* FUNCTION
*    OV5640YUV_SetGain
*
* DESCRIPTION
*    This function is to set global gain to sensor.
*
* PARAMETERS
*    gain : sensor global gain(base: 0x40)
*
* RETURNS
*    the actually gain set to sensor.
*
* GLOBALS AFFECTED
*
*************************************************************************/
//! Due to the OV5640 set gain will happen race condition.
//! It need to use a critical section to protect it.
//static atomic_t OV5640_SetGain_Flag;
//static wait_queue_head_t OV5640_SetGain_waitQueue;

void OV5640YUV_SetGain(UINT16 iGain)
{
    kal_uint8 iReg;
    int timeOut = 0;

#if 0
    if (atomic_read(&OV5640_SetGain_Flag) == 1) {
        timeOut = wait_event_interruptible_timeout(
                    OV5640_SetGain_waitQueue, atomic_read(&OV5640_SetGain_Flag) == 0, 1 * HZ);
        if (timeOut == 0) {
            SENSORDB("[OV5640YUV_SetGain] Set Gain Wait Queue time out \n");
            return;
        }
    }
    atomic_set(&OV5640_SetGain_Flag, 1);
#endif
    OV5640YUV_write_cmos_sensor(0x3212, 0x00);
    OV5640YUV_write_cmos_sensor(0x350B, (kal_uint32)iGain);
    OV5640YUV_write_cmos_sensor(0x3212, 0x10);
    OV5640YUV_write_cmos_sensor(0x3212, 0xA0);

#if 0
    atomic_set(&OV5640_SetGain_Flag, 0);
    wake_up_interruptible(&OV5640_SetGain_waitQueue);
#endif

}   /*  OV5640YUV_SetGain  */



/*************************************************************************
* FUNCTION
*   OV5640YUV_read_shutter
*
* DESCRIPTION
*   This function to  Get exposure time.
*
* PARAMETERS
*   None
*
* RETURNS
*   shutter : exposured lines
*
* GLOBALS AFFECTED
*
*************************************************************************/
UINT16 OV5640YUV_read_shutter(void)
{
    kal_uint8 temp_reg1, temp_reg2, temp_reg3;
    kal_uint16 temp_reg;
    temp_reg1 = OV5640YUV_read_cmos_sensor(0x3500);
    temp_reg2 = OV5640YUV_read_cmos_sensor(0x3501);
    temp_reg3 = OV5640YUV_read_cmos_sensor(0x3502);

    // SENSORDB("ov5640read shutter 0x3500=0x%x,0x3501=0x%x,0x3502=0x%x\n",
    //	temp_reg1,temp_reg2,temp_reg3);
    temp_reg = ((temp_reg1<<12) & 0xF000) | ((temp_reg2<<4) & 0x0FF0) | ((temp_reg3>>4) & 0x0F);
    //SENSORDB("ov5640read shutter = 0x%x\n", temp_reg);
    return (UINT16)temp_reg;
}

void OV5640YUV_write_shutter(kal_uint16 shutter)
{
    kal_uint16 iExp = shutter;
    kal_uint16 OV5640_g_iExtra_ExpLines = 0 ;
    int timeOut = 0;

    OV5640YUV_write_cmos_sensor(0x3500, (iExp >> 12) & 0xFF);
    OV5640YUV_write_cmos_sensor(0x3501, (iExp >> 4 ) & 0xFF);
    OV5640YUV_write_cmos_sensor(0x3502, (iExp <<4 ) & 0xFF);
}   /* write_OV5640_shutter */


/*************************************************************************
* FUNCTION
*   OV5640YUV_SetShutter
*
* DESCRIPTION
*   This function set e-shutter of OV5640 to change exposure time.
*
* PARAMETERS
*   shutter : exposured lines
*
* RETURNS
*   None
*
* GLOBALS AFFECTED
*
*************************************************************************/
void OV5640YUV_SetShutter(kal_uint16 iShutter)
{

    if (iShutter < 1)
        iShutter = 1;

    OV5640YUV_pv_exposure_lines = iShutter;
    OV5640YUV_write_shutter(iShutter);
    //SENSORDB("iShutter = %d\n", iShutter);

}   /*  OV5640YUV_SetShutter   */




/*************************************************************************
* FUNCTION
*    read_OV5640YUV_gain
*
* DESCRIPTION
*    This function is to set global gain to sensor.
*
* PARAMETERS
*    None
*
* RETURNS
*    gain : sensor global gain(base: 0x40)
*
* GLOBALS AFFECTED
*
*************************************************************************/
kal_uint16 read_OV5640YUV_gain(void)
{

    kal_uint8 temp_gain;
    kal_uint16 gain;

    gain = OV5640YUV_read_cmos_sensor(0x350B);

    return gain;
}  /* read_OV5640YUV_gain */

void write_OV5640YUV_gain(kal_uint16 gain)
{
    OV5640YUV_SetGain(gain);
}


/*************************************************************************
* FUNCTION
*   OV5640YUVPreview
*
* DESCRIPTION
*   This function start the sensor preview.
*
* PARAMETERS
*   *image_window : address pointer of pixel numbers in one period of HSYNC
*  *sensor_config_data : address pointer of line numbers in one period of VSYNC
*
* RETURNS
*   None
*
* GLOBALS AFFECTED
*
*************************************************************************/
UINT32 OV5640YUVPreview()
{
 //   kal_uint16 iStartX = 0, iStartY = 0;

   g_iOV5640YUV_Mode = OV5640_MODE_PREVIEW;

    OV5640YUV_write_cmos_sensor(0x4202,0x0f);
   // msleep(30);

    msleep(5);

    OV5640YUV_set_720P();

    OV5640YUV_write_cmos_sensor(0x4202,0x00);
  //  msleep(30);


  // dg cancle  ,donot focus  start,otherwise picture is not working well.
   //dg  use after
   // OV5640YUV_write_cmos_sensor(0x3023,0x01);
  //  OV5640YUV_write_cmos_sensor(0x3022,0x04);

#if 0
    if (tem){
        OV5640YUV_SetShutter(back_shutter);
        write_OV5640YUV_gain(back_pv_gain);
    }
    tem =0;
#endif

    //OV5640YUV_write_cmos_sensor(0x3820, 0x46);
    //OV5640YUV_write_cmos_sensor(0x3821, 0x00);
/*
    if(sensor_config_data->SensorOperationMode==MSDK_SENSOR_OPERATION_MODE_VIDEO)		// MPEG4 Encode Mode
    {
        OV5640YUV_MPEG4_encode_mode = KAL_TRUE;
    }
    else
    {
        OV5640YUV_MPEG4_encode_mode = KAL_FALSE;
    }

    iStartX += OV5640_IMAGE_SENSOR_PV_STARTX;
    iStartY += OV5640_IMAGE_SENSOR_PV_STARTY;
*/

    // sensor_config_data->SensorImageMirror = IMAGE_HV_MIRROR;
    // OV5640YUV_Set_Mirror_Flip(sensor_config_data->SensorImageMirror);
    /*************************************************************************************************************/

    //dg cancle 2015-07-18
    //OV5640YUV_write_cmos_sensor(0x3820,0x47);
    //OV5640YUV_write_cmos_sensor(0x3821,0x01);
   // OV5640YUV_write_cmos_sensor(0x4514,0x00);
    /*************************************************************************************************************/

#if 0
    OV5640YUV_dummy_pixels = 0;
    OV5640YUV_dummy_lines = 0;
    OV5640YUV_PV_dummy_pixels = OV5640YUV_dummy_pixels;
    OV5640YUV_PV_dummy_lines = OV5640YUV_dummy_lines;
    //OV5640YUV_SetDummy(OV5640YUV_dummy_pixels, OV5640YUV_dummy_lines);
#endif

    //OV5640YUV_NightMode(OV5640YUV_night_mode);
    OV5640YUV_NightMode(false);

#if 0
    memcpy(&OV5640YUVSensorConfigData, sensor_config_data, sizeof(MSDK_SENSOR_CONFIG_STRUCT));
    image_window->GrabStartX= iStartX;
    image_window->GrabStartY= iStartY;
    image_window->ExposureWindowWidth= OV5640_IMAGE_SENSOR_PV_WIDTH - 2*iStartX;
    image_window->ExposureWindowHeight= OV5640_IMAGE_SENSOR_PV_HEIGHT - 2*iStartY;
#endif
    return 0;
}



UINT32 OV5640YUVCapture( )
{
    kal_uint32 shutter = 0;
    kal_uint32 temp_shutter = 0;
    kal_uint16 iStartX = 0, iStartY = 0;
    kal_uint32 pv_gain = 0;
    kal_uint8 temp = 0;//for night mode


    if(g_iOV5640YUV_Mode == OV5640_MODE_PREVIEW)
    {
        g_iOV5640YUV_Mode = OV5640_MODE_CAPTURE;

      //  if(sensor_config_data->EnableShutterTansfer==KAL_TRUE)
         //   shutter=sensor_config_data->CaptureShutter;

        temp= OV5640YUV_read_cmos_sensor(0x3a00);
        OV5640YUV_write_cmos_sensor(0x3a00,temp&0xfb);

        OV5640YUV_set_AE_mode(KAL_FALSE);
        //OV5640YUV_set_AWB_mode(KAL_FALSE);

        shutter = OV5640YUV_read_shutter();

        pv_gain = read_OV5640YUV_gain();
        back_shutter = shutter;
        back_pv_gain = pv_gain;

        tem = 1;

        SENSORDB("Preview Shutter = %d, Gain = %d\n", shutter, pv_gain);

#if 0
        if ((image_window->ImageTargetWidth<= OV5640_IMAGE_SENSOR_PV_WIDTH) &&
                (image_window->ImageTargetHeight<= OV5640_IMAGE_SENSOR_PV_HEIGHT))
        {
            OV5640YUV_dummy_pixels= 0;
            OV5640YUV_dummy_lines = 0;
            iStartX = OV5640_IMAGE_SENSOR_PV_STARTX;
            iStartY = OV5640_IMAGE_SENSOR_PV_STARTY;
            image_window->GrabStartX=iStartX;
            image_window->GrabStartY=iStartY;
            image_window->ExposureWindowWidth=OV5640_IMAGE_SENSOR_PV_WIDTH - 2*iStartX;
            image_window->ExposureWindowHeight=OV5640_IMAGE_SENSOR_PV_HEIGHT- 2*iStartY;
        }
        else
        {
#endif
            OV5640_FOCUS_AD5820_Single_Focus();

            OV5640YUV_write_cmos_sensor(0x4202,0x0f);
            Sleep(30);
            OV5640YUV_set_5M();
            OV5640YUV_write_cmos_sensor(0x4202,0x00);
            Sleep(30);
#if 0
            OV5640YUV_dummy_pixels= 0;
            OV5640YUV_dummy_lines = 0;
            OV5640YUV_CAP_pclk = 560;
            OV5640YUV_PV_pclk = 560;

            //temp_shutter = (shutter*(OV5640_PV_PERIOD_PIXEL_NUMS_HTS+OV5640YUV_PV_dummy_pixels)*OV5640YUV_CAP_pclk)
            //			/(OV5640_FULL_PERIOD_PIXEL_NUMS_HTS+OV5640YUV_dummy_pixels)/OV5640YUV_PV_pclk;
            //shutter = (kal_uint32)(temp_shutter);

            shutter = shutter*4/3;

            SENSORDB("cap shutter calutaed = %d, 0x%x\n", shutter,shutter);
            iStartX = 2* OV5640_IMAGE_SENSOR_PV_STARTX;
            iStartY = 2* OV5640_IMAGE_SENSOR_PV_STARTY;
            image_window->GrabStartX=iStartX;
            image_window->GrabStartY=iStartY;
            image_window->ExposureWindowWidth=OV5640_IMAGE_SENSOR_FULL_WIDTH -2*iStartX;
            image_window->ExposureWindowHeight=OV5640_IMAGE_SENSOR_FULL_HEIGHT-2*iStartY;
        }

        sensor_config_data->Lines = image_window->ExposureWindowHeight;
        sensor_config_data->Shutter =shutter;

        OV5640YUV_SetDummy(OV5640YUV_dummy_pixels, OV5640YUV_dummy_lines);


#endif
        OV5640YUV_SetShutter(shutter);
        write_OV5640YUV_gain(pv_gain);
#if 0

        memcpy(&OV5640YUVSensorConfigData, sensor_config_data, sizeof(MSDK_SENSOR_CONFIG_STRUCT));
#endif
        // sensor_config_data->SensorImageMirror = IMAGE_NORMAL;
        // OV5640YUV_Set_Mirror_Flip(sensor_config_data->SensorImageMirror);
    }

    /*************************************************************************************************************/
    OV5640YUV_write_cmos_sensor(0x3820,0x46);
    OV5640YUV_write_cmos_sensor(0x3821,0x00);
    OV5640YUV_write_cmos_sensor(0x4514,0x88);
    /*************************************************************************************************************/

    return ERROR_NONE;
}


#endif  //end dg add 2015-07-15












/* add by cym 20130605 */
static int ov5640_power(int flag)
{
        int err;
        printk("cym: ov5640 sensor is power %s\n",flag == 1 ?"on":"off");
        //Attention: Power On the all the camera module when system turn on
        //Here only control the reset&&powerdown pin

        /* Camera A */
        if(1 == flag)
        {
                //poweron
#ifndef CONFIG_TC4_EVT
        regulator_enable(ov_vdd18_cam_regulator);
               udelay(10);
                regulator_enable(ov_vdd28_cam_regulator);
               udelay(10);
                regulator_enable(ov_vdd5m_cam_regulator); //DOVDD  DVDD 1.8v
               udelay(10);
                regulator_enable(ov_vddaf_cam_regulator);         //AVDD 2.8v
               udelay(10);
#endif
#if 1
                //pwdn		GPF0_5: 2M PWDN
                err = gpio_request(EXYNOS4_GPF0(5), "GPF0_5");
                if (err)
                        printk(KERN_ERR "#### failed to request GPF0_5 ####\n");
                s3c_gpio_setpull(EXYNOS4_GPF0(5), S3C_GPIO_PULL_NONE);
                gpio_direction_output(EXYNOS4_GPF0(5), 1);
                gpio_free(EXYNOS4_GPF0(5));
#endif
                //pwdn1	GPF2_4: 5M PWDN
                err = gpio_request(EXYNOS4_GPL0(3), "GPL0_3");
                if (err)
                        printk(KERN_ERR "#### failed to request GPL0_3 ####\n");
                s3c_gpio_setpull(EXYNOS4_GPL0(3), S3C_GPIO_PULL_NONE);
                gpio_direction_output(EXYNOS4_GPL0(3), 0);
                gpio_free(EXYNOS4_GPL0(3));
                msleep(20);

                //reset
                err = gpio_request(EXYNOS4_GPL0(1), "GPL0_1");
                if (err)
                        printk(KERN_ERR "#### failed to request GPL0_1 ####\n");
                s3c_gpio_setpull(EXYNOS4_GPL0(1), S3C_GPIO_PULL_NONE);
                gpio_direction_output(EXYNOS4_GPL0(1), 1);
                msleep(10);
                gpio_direction_output(EXYNOS4_GPL0(1), 0);
                msleep(10);
                gpio_direction_output(EXYNOS4_GPL0(1), 1);

                gpio_free(EXYNOS4_GPL0(1));
                msleep(20);
        }
        else
        {
			err = gpio_request(EXYNOS4_GPL0(1), "GPF0");
			if (err)
				printk(KERN_ERR "#### failed to request GPF0_4 ####\n");
			s3c_gpio_setpull(EXYNOS4_GPL0(1), S3C_GPIO_PULL_NONE);
			gpio_direction_output(EXYNOS4_GPL0(1), 0);
			gpio_free(EXYNOS4_GPL0(1));

#if 1
                //powerdown	GPF0_5: 2M PWDN
                err = gpio_request(EXYNOS4_GPF0(5), "GPF0_5");
                if (err)
                        printk(KERN_ERR "#### failed to request GPE0_5 ####\n");
                s3c_gpio_setpull(EXYNOS4_GPF0(5), S3C_GPIO_PULL_NONE);
                gpio_direction_output(EXYNOS4_GPF0(5), 1);
                gpio_free(EXYNOS4_GPF0(5));
#endif
		 //pwdn1			GPF2_4: 5M PWDN
                err = gpio_request(EXYNOS4_GPL0(3), "GPL0_3");
                if (err)
                        printk(KERN_ERR "#### failed to request GPF2_4 ####\n");
                s3c_gpio_setpull(EXYNOS4_GPL0(3), S3C_GPIO_PULL_NONE);
                gpio_direction_output(EXYNOS4_GPL0(3), 1);
                gpio_free(EXYNOS4_GPL0(3));
#ifndef CONFIG_TC4_EVT
                regulator_disable(ov_vdd18_cam_regulator);
               udelay(10);
                regulator_disable(ov_vdd28_cam_regulator);
               udelay(10);
                regulator_disable(ov_vdd5m_cam_regulator);
               udelay(10);
                regulator_disable(ov_vddaf_cam_regulator);
               udelay(10);
#endif
        }

        return 0;
}

#define DEV_DBG_EN   	1 
#define REG_ADDR_STEP 2
#define REG_DATA_STEP 1
#define REG_STEP 			(REG_ADDR_STEP+REG_DATA_STEP)

#define csi_dev_err(x,arg...) printk(KERN_INFO"[OV5640]"x,##arg)
#define csi_dev_print(x,arg...) printk(KERN_INFO"[OV5640]"x,##arg)

struct regval_list {
	unsigned char reg_num[REG_ADDR_STEP];
	unsigned char value[REG_DATA_STEP];
};

static char ov5640_sensor_af_fw_regs[] = {
	0x02, 0x0f, 0xd6, 0x02, 0x0a, 0x39, 0xc2, 0x01, 0x22, 0x22, 0x00, 0x02, 0x0f, 0xb2, 0xe5, 0x1f, //0x8000,
	0x70, 0x72, 0xf5, 0x1e, 0xd2, 0x35, 0xff, 0xef, 0x25, 0xe0, 0x24, 0x4e, 0xf8, 0xe4, 0xf6, 0x08, //0x8010,
	0xf6, 0x0f, 0xbf, 0x34, 0xf2, 0x90, 0x0e, 0x93, 0xe4, 0x93, 0xff, 0xe5, 0x4b, 0xc3, 0x9f, 0x50, //0x8020,
	0x04, 0x7f, 0x05, 0x80, 0x02, 0x7f, 0xfb, 0x78, 0xbd, 0xa6, 0x07, 0x12, 0x0f, 0x04, 0x40, 0x04, //0x8030,
	0x7f, 0x03, 0x80, 0x02, 0x7f, 0x30, 0x78, 0xbc, 0xa6, 0x07, 0xe6, 0x18, 0xf6, 0x08, 0xe6, 0x78, //0x8040,
	0xb9, 0xf6, 0x78, 0xbc, 0xe6, 0x78, 0xba, 0xf6, 0x78, 0xbf, 0x76, 0x33, 0xe4, 0x08, 0xf6, 0x78, //0x8050,
	0xb8, 0x76, 0x01, 0x75, 0x4a, 0x02, 0x78, 0xb6, 0xf6, 0x08, 0xf6, 0x74, 0xff, 0x78, 0xc1, 0xf6, //0x8060,
	0x08, 0xf6, 0x75, 0x1f, 0x01, 0x78, 0xbc, 0xe6, 0x75, 0xf0, 0x05, 0xa4, 0xf5, 0x4b, 0x12, 0x0a, //0x8070,
	0xff, 0xc2, 0x37, 0x22, 0x78, 0xb8, 0xe6, 0xd3, 0x94, 0x00, 0x40, 0x02, 0x16, 0x22, 0xe5, 0x1f, //0x8080,
	0xb4, 0x05, 0x23, 0xe4, 0xf5, 0x1f, 0xc2, 0x01, 0x78, 0xb6, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x78, //0x8090,
	0x4e, 0xa6, 0x06, 0x08, 0xa6, 0x07, 0xa2, 0x37, 0xe4, 0x33, 0xf5, 0x3c, 0x90, 0x30, 0x28, 0xf0, //0x80a0,
	0x75, 0x1e, 0x10, 0xd2, 0x35, 0x22, 0xe5, 0x4b, 0x75, 0xf0, 0x05, 0x84, 0x78, 0xbc, 0xf6, 0x90, //0x80b0,
	0x0e, 0x8c, 0xe4, 0x93, 0xff, 0x25, 0xe0, 0x24, 0x0a, 0xf8, 0xe6, 0xfc, 0x08, 0xe6, 0xfd, 0x78, //0x80c0,
	0xbc, 0xe6, 0x25, 0xe0, 0x24, 0x4e, 0xf8, 0xa6, 0x04, 0x08, 0xa6, 0x05, 0xef, 0x12, 0x0f, 0x0b, //0x80d0,
	0xd3, 0x78, 0xb7, 0x96, 0xee, 0x18, 0x96, 0x40, 0x0d, 0x78, 0xbc, 0xe6, 0x78, 0xb9, 0xf6, 0x78, //0x80e0,
	0xb6, 0xa6, 0x06, 0x08, 0xa6, 0x07, 0x90, 0x0e, 0x8c, 0xe4, 0x93, 0x12, 0x0f, 0x0b, 0xc3, 0x78, //0x80f0,
	0xc2, 0x96, 0xee, 0x18, 0x96, 0x50, 0x0d, 0x78, 0xbc, 0xe6, 0x78, 0xba, 0xf6, 0x78, 0xc1, 0xa6, //0x8100,
	0x06, 0x08, 0xa6, 0x07, 0x78, 0xb6, 0xe6, 0xfe, 0x08, 0xe6, 0xc3, 0x78, 0xc2, 0x96, 0xff, 0xee, //0x8110,
	0x18, 0x96, 0x78, 0xc3, 0xf6, 0x08, 0xa6, 0x07, 0x90, 0x0e, 0x95, 0xe4, 0x18, 0x12, 0x0e, 0xe9, //0x8120,
	0x40, 0x02, 0xd2, 0x37, 0x78, 0xbc, 0xe6, 0x08, 0x26, 0x08, 0xf6, 0xe5, 0x1f, 0x64, 0x01, 0x70, //0x8130,
	0x4a, 0xe6, 0xc3, 0x78, 0xc0, 0x12, 0x0e, 0xdf, 0x40, 0x05, 0x12, 0x0e, 0xda, 0x40, 0x39, 0x12, //0x8140,
	0x0f, 0x02, 0x40, 0x04, 0x7f, 0xfe, 0x80, 0x02, 0x7f, 0x02, 0x78, 0xbd, 0xa6, 0x07, 0x78, 0xb9, //0x8150,
	0xe6, 0x24, 0x03, 0x78, 0xbf, 0xf6, 0x78, 0xb9, 0xe6, 0x24, 0xfd, 0x78, 0xc0, 0xf6, 0x12, 0x0f, //0x8160,
	0x02, 0x40, 0x06, 0x78, 0xc0, 0xe6, 0xff, 0x80, 0x04, 0x78, 0xbf, 0xe6, 0xff, 0x78, 0xbe, 0xa6, //0x8170,
	0x07, 0x75, 0x1f, 0x02, 0x78, 0xb8, 0x76, 0x01, 0x02, 0x02, 0x4a, 0xe5, 0x1f, 0x64, 0x02, 0x60, //0x8180,
	0x03, 0x02, 0x02, 0x2a, 0x78, 0xbe, 0xe6, 0xff, 0xc3, 0x78, 0xc0, 0x12, 0x0e, 0xe0, 0x40, 0x08, //0x8190,
	0x12, 0x0e, 0xda, 0x50, 0x03, 0x02, 0x02, 0x28, 0x12, 0x0f, 0x02, 0x40, 0x04, 0x7f, 0xff, 0x80, //0x81a0,
	0x02, 0x7f, 0x01, 0x78, 0xbd, 0xa6, 0x07, 0x78, 0xb9, 0xe6, 0x04, 0x78, 0xbf, 0xf6, 0x78, 0xb9, //0x81b0,
	0xe6, 0x14, 0x78, 0xc0, 0xf6, 0x18, 0x12, 0x0f, 0x04, 0x40, 0x04, 0xe6, 0xff, 0x80, 0x02, 0x7f, //0x81c0,
	0x00, 0x78, 0xbf, 0xa6, 0x07, 0xd3, 0x08, 0xe6, 0x64, 0x80, 0x94, 0x80, 0x40, 0x04, 0xe6, 0xff, //0x81d0,
	0x80, 0x02, 0x7f, 0x00, 0x78, 0xc0, 0xa6, 0x07, 0xc3, 0x18, 0xe6, 0x64, 0x80, 0x94, 0xb3, 0x50, //0x81e0,
	0x04, 0xe6, 0xff, 0x80, 0x02, 0x7f, 0x33, 0x78, 0xbf, 0xa6, 0x07, 0xc3, 0x08, 0xe6, 0x64, 0x80, //0x81f0,
	0x94, 0xb3, 0x50, 0x04, 0xe6, 0xff, 0x80, 0x02, 0x7f, 0x33, 0x78, 0xc0, 0xa6, 0x07, 0x12, 0x0f, //0x8200,
	0x02, 0x40, 0x06, 0x78, 0xc0, 0xe6, 0xff, 0x80, 0x04, 0x78, 0xbf, 0xe6, 0xff, 0x78, 0xbe, 0xa6, //0x8210,
	0x07, 0x75, 0x1f, 0x03, 0x78, 0xb8, 0x76, 0x01, 0x80, 0x20, 0xe5, 0x1f, 0x64, 0x03, 0x70, 0x26, //0x8220,
	0x78, 0xbe, 0xe6, 0xff, 0xc3, 0x78, 0xc0, 0x12, 0x0e, 0xe0, 0x40, 0x05, 0x12, 0x0e, 0xda, 0x40, //0x8230,
	0x09, 0x78, 0xb9, 0xe6, 0x78, 0xbe, 0xf6, 0x75, 0x1f, 0x04, 0x78, 0xbe, 0xe6, 0x75, 0xf0, 0x05, //0x8240,
	0xa4, 0xf5, 0x4b, 0x02, 0x0a, 0xff, 0xe5, 0x1f, 0xb4, 0x04, 0x10, 0x90, 0x0e, 0x94, 0xe4, 0x78, //0x8250,
	0xc3, 0x12, 0x0e, 0xe9, 0x40, 0x02, 0xd2, 0x37, 0x75, 0x1f, 0x05, 0x22, 0x30, 0x01, 0x03, 0x02, //0x8260,
	0x04, 0xc0, 0x30, 0x02, 0x03, 0x02, 0x04, 0xc0, 0x90, 0x51, 0xa5, 0xe0, 0x78, 0x93, 0xf6, 0xa3, //0x8270,
	0xe0, 0x08, 0xf6, 0xa3, 0xe0, 0x08, 0xf6, 0xe5, 0x1f, 0x70, 0x3c, 0x75, 0x1e, 0x20, 0xd2, 0x35, //0x8280,
	0x12, 0x0c, 0x7a, 0x78, 0x7e, 0xa6, 0x06, 0x08, 0xa6, 0x07, 0x78, 0x8b, 0xa6, 0x09, 0x18, 0x76, //0x8290,
	0x01, 0x12, 0x0c, 0x5b, 0x78, 0x4e, 0xa6, 0x06, 0x08, 0xa6, 0x07, 0x78, 0x8b, 0xe6, 0x78, 0x6e, //0x82a0,
	0xf6, 0x75, 0x1f, 0x01, 0x78, 0x93, 0xe6, 0x78, 0x90, 0xf6, 0x78, 0x94, 0xe6, 0x78, 0x91, 0xf6, //0x82b0,
	0x78, 0x95, 0xe6, 0x78, 0x92, 0xf6, 0x22, 0x79, 0x90, 0xe7, 0xd3, 0x78, 0x93, 0x96, 0x40, 0x05, //0x82c0,
	0xe7, 0x96, 0xff, 0x80, 0x08, 0xc3, 0x79, 0x93, 0xe7, 0x78, 0x90, 0x96, 0xff, 0x78, 0x88, 0x76, //0x82d0,
	0x00, 0x08, 0xa6, 0x07, 0x79, 0x91, 0xe7, 0xd3, 0x78, 0x94, 0x96, 0x40, 0x05, 0xe7, 0x96, 0xff, //0x82e0,
	0x80, 0x08, 0xc3, 0x79, 0x94, 0xe7, 0x78, 0x91, 0x96, 0xff, 0x12, 0x0c, 0x8e, 0x79, 0x92, 0xe7, //0x82f0,
	0xd3, 0x78, 0x95, 0x96, 0x40, 0x05, 0xe7, 0x96, 0xff, 0x80, 0x08, 0xc3, 0x79, 0x95, 0xe7, 0x78, //0x8300,
	0x92, 0x96, 0xff, 0x12, 0x0c, 0x8e, 0x12, 0x0c, 0x5b, 0x78, 0x8a, 0xe6, 0x25, 0xe0, 0x24, 0x4e, //0x8310,
	0xf8, 0xa6, 0x06, 0x08, 0xa6, 0x07, 0x78, 0x8a, 0xe6, 0x24, 0x6e, 0xf8, 0xa6, 0x09, 0x78, 0x8a, //0x8320,
	0xe6, 0x24, 0x01, 0xff, 0xe4, 0x33, 0xfe, 0xd3, 0xef, 0x94, 0x0f, 0xee, 0x64, 0x80, 0x94, 0x80, //0x8330,
	0x40, 0x04, 0x7f, 0x00, 0x80, 0x05, 0x78, 0x8a, 0xe6, 0x04, 0xff, 0x78, 0x8a, 0xa6, 0x07, 0xe5, //0x8340,
	0x1f, 0xb4, 0x01, 0x0a, 0xe6, 0x60, 0x03, 0x02, 0x04, 0xc0, 0x75, 0x1f, 0x02, 0x22, 0x12, 0x0c, //0x8350,
	0x7a, 0x78, 0x80, 0xa6, 0x06, 0x08, 0xa6, 0x07, 0x12, 0x0c, 0x7a, 0x78, 0x82, 0xa6, 0x06, 0x08, //0x8360,
	0xa6, 0x07, 0x78, 0x6e, 0xe6, 0x78, 0x8c, 0xf6, 0x78, 0x6e, 0xe6, 0x78, 0x8d, 0xf6, 0x7f, 0x01, //0x8370,
	0xef, 0x25, 0xe0, 0x24, 0x4f, 0xf9, 0xc3, 0x78, 0x81, 0xe6, 0x97, 0x18, 0xe6, 0x19, 0x97, 0x50, //0x8380,
	0x0a, 0x12, 0x0c, 0x82, 0x78, 0x80, 0xa6, 0x04, 0x08, 0xa6, 0x05, 0x74, 0x6e, 0x2f, 0xf9, 0x78, //0x8390,
	0x8c, 0xe6, 0xc3, 0x97, 0x50, 0x08, 0x74, 0x6e, 0x2f, 0xf8, 0xe6, 0x78, 0x8c, 0xf6, 0xef, 0x25, //0x83a0,
	0xe0, 0x24, 0x4f, 0xf9, 0xd3, 0x78, 0x83, 0xe6, 0x97, 0x18, 0xe6, 0x19, 0x97, 0x40, 0x0a, 0x12, //0x83b0,
	0x0c, 0x82, 0x78, 0x82, 0xa6, 0x04, 0x08, 0xa6, 0x05, 0x74, 0x6e, 0x2f, 0xf9, 0x78, 0x8d, 0xe6, //0x83c0,
	0xd3, 0x97, 0x40, 0x08, 0x74, 0x6e, 0x2f, 0xf8, 0xe6, 0x78, 0x8d, 0xf6, 0x0f, 0xef, 0x64, 0x10, //0x83d0,
	0x70, 0x9e, 0xc3, 0x79, 0x81, 0xe7, 0x78, 0x83, 0x96, 0xff, 0x19, 0xe7, 0x18, 0x96, 0x78, 0x84, //0x83e0,
	0xf6, 0x08, 0xa6, 0x07, 0xc3, 0x79, 0x8c, 0xe7, 0x78, 0x8d, 0x96, 0x08, 0xf6, 0xd3, 0x79, 0x81, //0x83f0,
	0xe7, 0x78, 0x7f, 0x96, 0x19, 0xe7, 0x18, 0x96, 0x40, 0x05, 0x09, 0xe7, 0x08, 0x80, 0x06, 0xc3, //0x8400,
	0x79, 0x7f, 0xe7, 0x78, 0x81, 0x96, 0xff, 0x19, 0xe7, 0x18, 0x96, 0xfe, 0x78, 0x86, 0xa6, 0x06, //0x8410,
	0x08, 0xa6, 0x07, 0x79, 0x8c, 0xe7, 0xd3, 0x78, 0x8b, 0x96, 0x40, 0x05, 0xe7, 0x96, 0xff, 0x80, //0x8420,
	0x08, 0xc3, 0x79, 0x8b, 0xe7, 0x78, 0x8c, 0x96, 0xff, 0x78, 0x8f, 0xa6, 0x07, 0xe5, 0x1f, 0x64, //0x8430,
	0x02, 0x70, 0x69, 0x90, 0x0e, 0x91, 0x93, 0xff, 0x18, 0xe6, 0xc3, 0x9f, 0x50, 0x72, 0x12, 0x0c, //0x8440,
	0x4a, 0x12, 0x0c, 0x2f, 0x90, 0x0e, 0x8e, 0x12, 0x0c, 0x38, 0x78, 0x80, 0x12, 0x0c, 0x6b, 0x7b, //0x8450,
	0x04, 0x12, 0x0c, 0x1d, 0xc3, 0x12, 0x06, 0x45, 0x50, 0x56, 0x90, 0x0e, 0x92, 0xe4, 0x93, 0xff, //0x8460,
	0x78, 0x8f, 0xe6, 0x9f, 0x40, 0x02, 0x80, 0x11, 0x90, 0x0e, 0x90, 0xe4, 0x93, 0xff, 0xd3, 0x78, //0x8470,
	0x89, 0xe6, 0x9f, 0x18, 0xe6, 0x94, 0x00, 0x40, 0x03, 0x75, 0x1f, 0x05, 0x12, 0x0c, 0x4a, 0x12, //0x8480,
	0x0c, 0x2f, 0x90, 0x0e, 0x8f, 0x12, 0x0c, 0x38, 0x78, 0x7e, 0x12, 0x0c, 0x6b, 0x7b, 0x40, 0x12, //0x8490,
	0x0c, 0x1d, 0xd3, 0x12, 0x06, 0x45, 0x40, 0x18, 0x75, 0x1f, 0x05, 0x22, 0xe5, 0x1f, 0xb4, 0x05, //0x84a0,
	0x0f, 0xd2, 0x01, 0xc2, 0x02, 0xe4, 0xf5, 0x1f, 0xf5, 0x1e, 0xd2, 0x35, 0xd2, 0x33, 0xd2, 0x36, //0x84b0,
	0x22, 0xef, 0x8d, 0xf0, 0xa4, 0xa8, 0xf0, 0xcf, 0x8c, 0xf0, 0xa4, 0x28, 0xce, 0x8d, 0xf0, 0xa4, //0x84c0,
	0x2e, 0xfe, 0x22, 0xbc, 0x00, 0x0b, 0xbe, 0x00, 0x29, 0xef, 0x8d, 0xf0, 0x84, 0xff, 0xad, 0xf0, //0x84d0,
	0x22, 0xe4, 0xcc, 0xf8, 0x75, 0xf0, 0x08, 0xef, 0x2f, 0xff, 0xee, 0x33, 0xfe, 0xec, 0x33, 0xfc, //0x84e0,
	0xee, 0x9d, 0xec, 0x98, 0x40, 0x05, 0xfc, 0xee, 0x9d, 0xfe, 0x0f, 0xd5, 0xf0, 0xe9, 0xe4, 0xce, //0x84f0,
	0xfd, 0x22, 0xed, 0xf8, 0xf5, 0xf0, 0xee, 0x84, 0x20, 0xd2, 0x1c, 0xfe, 0xad, 0xf0, 0x75, 0xf0, //0x8500,
	0x08, 0xef, 0x2f, 0xff, 0xed, 0x33, 0xfd, 0x40, 0x07, 0x98, 0x50, 0x06, 0xd5, 0xf0, 0xf2, 0x22, //0x8510,
	0xc3, 0x98, 0xfd, 0x0f, 0xd5, 0xf0, 0xea, 0x22, 0xe8, 0x8f, 0xf0, 0xa4, 0xcc, 0x8b, 0xf0, 0xa4, //0x8520,
	0x2c, 0xfc, 0xe9, 0x8e, 0xf0, 0xa4, 0x2c, 0xfc, 0x8a, 0xf0, 0xed, 0xa4, 0x2c, 0xfc, 0xea, 0x8e, //0x8530,
	0xf0, 0xa4, 0xcd, 0xa8, 0xf0, 0x8b, 0xf0, 0xa4, 0x2d, 0xcc, 0x38, 0x25, 0xf0, 0xfd, 0xe9, 0x8f, //0x8540,
	0xf0, 0xa4, 0x2c, 0xcd, 0x35, 0xf0, 0xfc, 0xeb, 0x8e, 0xf0, 0xa4, 0xfe, 0xa9, 0xf0, 0xeb, 0x8f, //0x8550,
	0xf0, 0xa4, 0xcf, 0xc5, 0xf0, 0x2e, 0xcd, 0x39, 0xfe, 0xe4, 0x3c, 0xfc, 0xea, 0xa4, 0x2d, 0xce, //0x8560,
	0x35, 0xf0, 0xfd, 0xe4, 0x3c, 0xfc, 0x22, 0x75, 0xf0, 0x08, 0x75, 0x82, 0x00, 0xef, 0x2f, 0xff, //0x8570,
	0xee, 0x33, 0xfe, 0xcd, 0x33, 0xcd, 0xcc, 0x33, 0xcc, 0xc5, 0x82, 0x33, 0xc5, 0x82, 0x9b, 0xed, //0x8580,
	0x9a, 0xec, 0x99, 0xe5, 0x82, 0x98, 0x40, 0x0c, 0xf5, 0x82, 0xee, 0x9b, 0xfe, 0xed, 0x9a, 0xfd, //0x8590,
	0xec, 0x99, 0xfc, 0x0f, 0xd5, 0xf0, 0xd6, 0xe4, 0xce, 0xfb, 0xe4, 0xcd, 0xfa, 0xe4, 0xcc, 0xf9, //0x85a0,
	0xa8, 0x82, 0x22, 0xb8, 0x00, 0xc1, 0xb9, 0x00, 0x59, 0xba, 0x00, 0x2d, 0xec, 0x8b, 0xf0, 0x84, //0x85b0,
	0xcf, 0xce, 0xcd, 0xfc, 0xe5, 0xf0, 0xcb, 0xf9, 0x78, 0x18, 0xef, 0x2f, 0xff, 0xee, 0x33, 0xfe, //0x85c0,
	0xed, 0x33, 0xfd, 0xec, 0x33, 0xfc, 0xeb, 0x33, 0xfb, 0x10, 0xd7, 0x03, 0x99, 0x40, 0x04, 0xeb, //0x85d0,
	0x99, 0xfb, 0x0f, 0xd8, 0xe5, 0xe4, 0xf9, 0xfa, 0x22, 0x78, 0x18, 0xef, 0x2f, 0xff, 0xee, 0x33, //0x85e0,
	0xfe, 0xed, 0x33, 0xfd, 0xec, 0x33, 0xfc, 0xc9, 0x33, 0xc9, 0x10, 0xd7, 0x05, 0x9b, 0xe9, 0x9a, //0x85f0,
	0x40, 0x07, 0xec, 0x9b, 0xfc, 0xe9, 0x9a, 0xf9, 0x0f, 0xd8, 0xe0, 0xe4, 0xc9, 0xfa, 0xe4, 0xcc, //0x8600,
	0xfb, 0x22, 0x75, 0xf0, 0x10, 0xef, 0x2f, 0xff, 0xee, 0x33, 0xfe, 0xed, 0x33, 0xfd, 0xcc, 0x33, //0x8610,
	0xcc, 0xc8, 0x33, 0xc8, 0x10, 0xd7, 0x07, 0x9b, 0xec, 0x9a, 0xe8, 0x99, 0x40, 0x0a, 0xed, 0x9b, //0x8620,
	0xfd, 0xec, 0x9a, 0xfc, 0xe8, 0x99, 0xf8, 0x0f, 0xd5, 0xf0, 0xda, 0xe4, 0xcd, 0xfb, 0xe4, 0xcc, //0x8630,
	0xfa, 0xe4, 0xc8, 0xf9, 0x22, 0xeb, 0x9f, 0xf5, 0xf0, 0xea, 0x9e, 0x42, 0xf0, 0xe9, 0x9d, 0x42, //0x8640,
	0xf0, 0xe8, 0x9c, 0x45, 0xf0, 0x22, 0xe8, 0x60, 0x0f, 0xec, 0xc3, 0x13, 0xfc, 0xed, 0x13, 0xfd, //0x8650,
	0xee, 0x13, 0xfe, 0xef, 0x13, 0xff, 0xd8, 0xf1, 0x22, 0xe8, 0x60, 0x0f, 0xef, 0xc3, 0x33, 0xff, //0x8660,
	0xee, 0x33, 0xfe, 0xed, 0x33, 0xfd, 0xec, 0x33, 0xfc, 0xd8, 0xf1, 0x22, 0xe4, 0x93, 0xfc, 0x74, //0x8670,
	0x01, 0x93, 0xfd, 0x74, 0x02, 0x93, 0xfe, 0x74, 0x03, 0x93, 0xff, 0x22, 0xe6, 0xfb, 0x08, 0xe6, //0x8680,
	0xf9, 0x08, 0xe6, 0xfa, 0x08, 0xe6, 0xcb, 0xf8, 0x22, 0xec, 0xf6, 0x08, 0xed, 0xf6, 0x08, 0xee, //0x8690,
	0xf6, 0x08, 0xef, 0xf6, 0x22, 0xa4, 0x25, 0x82, 0xf5, 0x82, 0xe5, 0xf0, 0x35, 0x83, 0xf5, 0x83, //0x86a0,
	0x22, 0xd0, 0x83, 0xd0, 0x82, 0xf8, 0xe4, 0x93, 0x70, 0x12, 0x74, 0x01, 0x93, 0x70, 0x0d, 0xa3, //0x86b0,
	0xa3, 0x93, 0xf8, 0x74, 0x01, 0x93, 0xf5, 0x82, 0x88, 0x83, 0xe4, 0x73, 0x74, 0x02, 0x93, 0x68, //0x86c0,
	0x60, 0xef, 0xa3, 0xa3, 0xa3, 0x80, 0xdf, 0x90, 0x38, 0x04, 0x78, 0x52, 0x12, 0x0b, 0xfd, 0x90, //0x86d0,
	0x38, 0x00, 0xe0, 0xfe, 0xa3, 0xe0, 0xfd, 0xed, 0xff, 0xc3, 0x12, 0x0b, 0x9e, 0x90, 0x38, 0x10, //0x86e0,
	0x12, 0x0b, 0x92, 0x90, 0x38, 0x06, 0x78, 0x54, 0x12, 0x0b, 0xfd, 0x90, 0x38, 0x02, 0xe0, 0xfe, //0x86f0,
	0xa3, 0xe0, 0xfd, 0xed, 0xff, 0xc3, 0x12, 0x0b, 0x9e, 0x90, 0x38, 0x12, 0x12, 0x0b, 0x92, 0xa3, //0x8700,
	0xe0, 0xb4, 0x31, 0x07, 0x78, 0x52, 0x79, 0x52, 0x12, 0x0c, 0x13, 0x90, 0x38, 0x14, 0xe0, 0xb4, //0x8710,
	0x71, 0x15, 0x78, 0x52, 0xe6, 0xfe, 0x08, 0xe6, 0x78, 0x02, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, //0x8720,
	0xf9, 0x79, 0x53, 0xf7, 0xee, 0x19, 0xf7, 0x90, 0x38, 0x15, 0xe0, 0xb4, 0x31, 0x07, 0x78, 0x54, //0x8730,
	0x79, 0x54, 0x12, 0x0c, 0x13, 0x90, 0x38, 0x15, 0xe0, 0xb4, 0x71, 0x15, 0x78, 0x54, 0xe6, 0xfe, //0x8740,
	0x08, 0xe6, 0x78, 0x02, 0xce, 0xc3, 0x13, 0xce, 0x13, 0xd8, 0xf9, 0x79, 0x55, 0xf7, 0xee, 0x19, //0x8750,
	0xf7, 0x79, 0x52, 0x12, 0x0b, 0xd9, 0x09, 0x12, 0x0b, 0xd9, 0xaf, 0x47, 0x12, 0x0b, 0xb2, 0xe5, //0x8760,
	0x44, 0xfb, 0x7a, 0x00, 0xfd, 0x7c, 0x00, 0x12, 0x04, 0xd3, 0x78, 0x5a, 0xa6, 0x06, 0x08, 0xa6, //0x8770,
	0x07, 0xaf, 0x45, 0x12, 0x0b, 0xb2, 0xad, 0x03, 0x7c, 0x00, 0x12, 0x04, 0xd3, 0x78, 0x56, 0xa6, //0x8780,
	0x06, 0x08, 0xa6, 0x07, 0xaf, 0x48, 0x78, 0x54, 0x12, 0x0b, 0xb4, 0xe5, 0x43, 0xfb, 0xfd, 0x7c, //0x8790,
	0x00, 0x12, 0x04, 0xd3, 0x78, 0x5c, 0xa6, 0x06, 0x08, 0xa6, 0x07, 0xaf, 0x46, 0x7e, 0x00, 0x78, //0x87a0,
	0x54, 0x12, 0x0b, 0xb6, 0xad, 0x03, 0x7c, 0x00, 0x12, 0x04, 0xd3, 0x78, 0x58, 0xa6, 0x06, 0x08, //0x87b0,
	0xa6, 0x07, 0xc3, 0x78, 0x5b, 0xe6, 0x94, 0x08, 0x18, 0xe6, 0x94, 0x00, 0x50, 0x05, 0x76, 0x00, //0x87c0,
	0x08, 0x76, 0x08, 0xc3, 0x78, 0x5d, 0xe6, 0x94, 0x08, 0x18, 0xe6, 0x94, 0x00, 0x50, 0x05, 0x76, //0x87d0,
	0x00, 0x08, 0x76, 0x08, 0x78, 0x5a, 0x12, 0x0b, 0xc6, 0xff, 0xd3, 0x78, 0x57, 0xe6, 0x9f, 0x18, //0x87e0,
	0xe6, 0x9e, 0x40, 0x0e, 0x78, 0x5a, 0xe6, 0x13, 0xfe, 0x08, 0xe6, 0x78, 0x57, 0x12, 0x0c, 0x08, //0x87f0,
	0x80, 0x04, 0x7e, 0x00, 0x7f, 0x00, 0x78, 0x5e, 0x12, 0x0b, 0xbe, 0xff, 0xd3, 0x78, 0x59, 0xe6, //0x8800,
	0x9f, 0x18, 0xe6, 0x9e, 0x40, 0x0e, 0x78, 0x5c, 0xe6, 0x13, 0xfe, 0x08, 0xe6, 0x78, 0x59, 0x12, //0x8810,
	0x0c, 0x08, 0x80, 0x04, 0x7e, 0x00, 0x7f, 0x00, 0xe4, 0xfc, 0xfd, 0x78, 0x62, 0x12, 0x06, 0x99, //0x8820,
	0x78, 0x5a, 0x12, 0x0b, 0xc6, 0x78, 0x57, 0x26, 0xff, 0xee, 0x18, 0x36, 0xfe, 0x78, 0x66, 0x12, //0x8830,
	0x0b, 0xbe, 0x78, 0x59, 0x26, 0xff, 0xee, 0x18, 0x36, 0xfe, 0xe4, 0xfc, 0xfd, 0x78, 0x6a, 0x12, //0x8840,
	0x06, 0x99, 0x12, 0x0b, 0xce, 0x78, 0x66, 0x12, 0x06, 0x8c, 0xd3, 0x12, 0x06, 0x45, 0x40, 0x08, //0x8850,
	0x12, 0x0b, 0xce, 0x78, 0x66, 0x12, 0x06, 0x99, 0x78, 0x54, 0x12, 0x0b, 0xd0, 0x78, 0x6a, 0x12, //0x8860,
	0x06, 0x8c, 0xd3, 0x12, 0x06, 0x45, 0x40, 0x0a, 0x78, 0x54, 0x12, 0x0b, 0xd0, 0x78, 0x6a, 0x12, //0x8870,
	0x06, 0x99, 0x78, 0x61, 0xe6, 0x90, 0x60, 0x01, 0xf0, 0x78, 0x65, 0xe6, 0xa3, 0xf0, 0x78, 0x69, //0x8880,
	0xe6, 0xa3, 0xf0, 0x78, 0x55, 0xe6, 0xa3, 0xf0, 0x7d, 0x01, 0x78, 0x61, 0x12, 0x0b, 0xe9, 0x24, //0x8890,
	0x01, 0x12, 0x0b, 0xa6, 0x78, 0x65, 0x12, 0x0b, 0xe9, 0x24, 0x02, 0x12, 0x0b, 0xa6, 0x78, 0x69, //0x88a0,
	0x12, 0x0b, 0xe9, 0x24, 0x03, 0x12, 0x0b, 0xa6, 0x78, 0x6d, 0x12, 0x0b, 0xe9, 0x24, 0x04, 0x12, //0x88b0,
	0x0b, 0xa6, 0x0d, 0xbd, 0x05, 0xd4, 0xc2, 0x0e, 0xc2, 0x06, 0x22, 0x85, 0x08, 0x41, 0x90, 0x30, //0x88c0,
	0x24, 0xe0, 0xf5, 0x3d, 0xa3, 0xe0, 0xf5, 0x3e, 0xa3, 0xe0, 0xf5, 0x3f, 0xa3, 0xe0, 0xf5, 0x40, //0x88d0,
	0xa3, 0xe0, 0xf5, 0x3c, 0xd2, 0x34, 0xe5, 0x41, 0x12, 0x06, 0xb1, 0x09, 0x31, 0x03, 0x09, 0x35, //0x88e0,
	0x04, 0x09, 0x3b, 0x05, 0x09, 0x3e, 0x06, 0x09, 0x41, 0x07, 0x09, 0x4a, 0x08, 0x09, 0x5b, 0x12, //0x88f0,
	0x09, 0x73, 0x18, 0x09, 0x89, 0x19, 0x09, 0x5e, 0x1a, 0x09, 0x6a, 0x1b, 0x09, 0xad, 0x80, 0x09, //0x8900,
	0xb2, 0x81, 0x0a, 0x1d, 0x8f, 0x0a, 0x09, 0x90, 0x0a, 0x1d, 0x91, 0x0a, 0x1d, 0x92, 0x0a, 0x1d, //0x8910,
	0x93, 0x0a, 0x1d, 0x94, 0x0a, 0x1d, 0x98, 0x0a, 0x17, 0x9f, 0x0a, 0x1a, 0xec, 0x00, 0x00, 0x0a, //0x8920,
	0x38, 0x12, 0x0f, 0x74, 0x22, 0x12, 0x0f, 0x74, 0xd2, 0x03, 0x22, 0xd2, 0x03, 0x22, 0xc2, 0x03, //0x8930,
	0x22, 0xa2, 0x37, 0xe4, 0x33, 0xf5, 0x3c, 0x02, 0x0a, 0x1d, 0xc2, 0x01, 0xc2, 0x02, 0xc2, 0x03, //0x8940,
	0x12, 0x0d, 0x0d, 0x75, 0x1e, 0x70, 0xd2, 0x35, 0x02, 0x0a, 0x1d, 0x02, 0x0a, 0x04, 0x85, 0x40, //0x8950,
	0x4a, 0x85, 0x3c, 0x4b, 0x12, 0x0a, 0xff, 0x02, 0x0a, 0x1d, 0x85, 0x4a, 0x40, 0x85, 0x4b, 0x3c, //0x8960,
	0x02, 0x0a, 0x1d, 0xe4, 0xf5, 0x22, 0xf5, 0x23, 0x85, 0x40, 0x31, 0x85, 0x3f, 0x30, 0x85, 0x3e, //0x8970,
	0x2f, 0x85, 0x3d, 0x2e, 0x12, 0x0f, 0x46, 0x80, 0x1f, 0x75, 0x22, 0x00, 0x75, 0x23, 0x01, 0x74, //0x8980,
	0xff, 0xf5, 0x2d, 0xf5, 0x2c, 0xf5, 0x2b, 0xf5, 0x2a, 0x12, 0x0f, 0x46, 0x85, 0x2d, 0x40, 0x85, //0x8990,
	0x2c, 0x3f, 0x85, 0x2b, 0x3e, 0x85, 0x2a, 0x3d, 0xe4, 0xf5, 0x3c, 0x80, 0x70, 0x12, 0x0f, 0x16, //0x89a0,
	0x80, 0x6b, 0x85, 0x3d, 0x45, 0x85, 0x3e, 0x46, 0xe5, 0x47, 0xc3, 0x13, 0xff, 0xe5, 0x45, 0xc3, //0x89b0,
	0x9f, 0x50, 0x02, 0x8f, 0x45, 0xe5, 0x48, 0xc3, 0x13, 0xff, 0xe5, 0x46, 0xc3, 0x9f, 0x50, 0x02, //0x89c0,
	0x8f, 0x46, 0xe5, 0x47, 0xc3, 0x13, 0xff, 0xfd, 0xe5, 0x45, 0x2d, 0xfd, 0xe4, 0x33, 0xfc, 0xe5, //0x89d0,
	0x44, 0x12, 0x0f, 0x90, 0x40, 0x05, 0xe5, 0x44, 0x9f, 0xf5, 0x45, 0xe5, 0x48, 0xc3, 0x13, 0xff, //0x89e0,
	0xfd, 0xe5, 0x46, 0x2d, 0xfd, 0xe4, 0x33, 0xfc, 0xe5, 0x43, 0x12, 0x0f, 0x90, 0x40, 0x05, 0xe5, //0x89f0,
	0x43, 0x9f, 0xf5, 0x46, 0x12, 0x06, 0xd7, 0x80, 0x14, 0x85, 0x40, 0x48, 0x85, 0x3f, 0x47, 0x85, //0x8a00,
	0x3e, 0x46, 0x85, 0x3d, 0x45, 0x80, 0x06, 0x02, 0x06, 0xd7, 0x12, 0x0d, 0x7e, 0x90, 0x30, 0x24, //0x8a10,
	0xe5, 0x3d, 0xf0, 0xa3, 0xe5, 0x3e, 0xf0, 0xa3, 0xe5, 0x3f, 0xf0, 0xa3, 0xe5, 0x40, 0xf0, 0xa3, //0x8a20,
	0xe5, 0x3c, 0xf0, 0x90, 0x30, 0x23, 0xe4, 0xf0, 0x22, 0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0xc0, //0x8a30,
	0xd0, 0x90, 0x3f, 0x0c, 0xe0, 0xf5, 0x32, 0xe5, 0x32, 0x30, 0xe3, 0x74, 0x30, 0x36, 0x66, 0x90, //0x8a40,
	0x60, 0x19, 0xe0, 0xf5, 0x0a, 0xa3, 0xe0, 0xf5, 0x0b, 0x90, 0x60, 0x1d, 0xe0, 0xf5, 0x14, 0xa3, //0x8a50,
	0xe0, 0xf5, 0x15, 0x90, 0x60, 0x21, 0xe0, 0xf5, 0x0c, 0xa3, 0xe0, 0xf5, 0x0d, 0x90, 0x60, 0x29, //0x8a60,
	0xe0, 0xf5, 0x0e, 0xa3, 0xe0, 0xf5, 0x0f, 0x90, 0x60, 0x31, 0xe0, 0xf5, 0x10, 0xa3, 0xe0, 0xf5, //0x8a70,
	0x11, 0x90, 0x60, 0x39, 0xe0, 0xf5, 0x12, 0xa3, 0xe0, 0xf5, 0x13, 0x30, 0x01, 0x06, 0x30, 0x33, //0x8a80,
	0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0x09, 0x30, 0x02, 0x06, 0x30, 0x33, 0x03, 0xd3, 0x80, 0x01, //0x8a90,
	0xc3, 0x92, 0x0a, 0x30, 0x33, 0x0c, 0x30, 0x03, 0x09, 0x20, 0x02, 0x06, 0x20, 0x01, 0x03, 0xd3, //0x8aa0,
	0x80, 0x01, 0xc3, 0x92, 0x0b, 0x90, 0x30, 0x01, 0xe0, 0x44, 0x40, 0xf0, 0xe0, 0x54, 0xbf, 0xf0, //0x8ab0,
	0xe5, 0x32, 0x30, 0xe1, 0x14, 0x30, 0x34, 0x11, 0x90, 0x30, 0x22, 0xe0, 0xf5, 0x08, 0xe4, 0xf0, //0x8ac0,
	0x30, 0x00, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0x08, 0xe5, 0x32, 0x30, 0xe5, 0x12, 0x90, 0x56, //0x8ad0,
	0xa1, 0xe0, 0xf5, 0x09, 0x30, 0x31, 0x09, 0x30, 0x05, 0x03, 0xd3, 0x80, 0x01, 0xc3, 0x92, 0x0d, //0x8ae0,
	0x90, 0x3f, 0x0c, 0xe5, 0x32, 0xf0, 0xd0, 0xd0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32, 0x90, //0x8af0,
	0x0e, 0x7e, 0xe4, 0x93, 0xfe, 0x74, 0x01, 0x93, 0xff, 0xc3, 0x90, 0x0e, 0x7c, 0x74, 0x01, 0x93, //0x8b00,
	0x9f, 0xff, 0xe4, 0x93, 0x9e, 0xfe, 0xe4, 0x8f, 0x3b, 0x8e, 0x3a, 0xf5, 0x39, 0xf5, 0x38, 0xab, //0x8b10,
	0x3b, 0xaa, 0x3a, 0xa9, 0x39, 0xa8, 0x38, 0xaf, 0x4b, 0xfc, 0xfd, 0xfe, 0x12, 0x05, 0x28, 0x12, //0x8b20,
	0x0d, 0xe1, 0xe4, 0x7b, 0xff, 0xfa, 0xf9, 0xf8, 0x12, 0x05, 0xb3, 0x12, 0x0d, 0xe1, 0x90, 0x0e, //0x8b30,
	0x69, 0xe4, 0x12, 0x0d, 0xf6, 0x12, 0x0d, 0xe1, 0xe4, 0x85, 0x4a, 0x37, 0xf5, 0x36, 0xf5, 0x35, //0x8b40,
	0xf5, 0x34, 0xaf, 0x37, 0xae, 0x36, 0xad, 0x35, 0xac, 0x34, 0xa3, 0x12, 0x0d, 0xf6, 0x8f, 0x37, //0x8b50,
	0x8e, 0x36, 0x8d, 0x35, 0x8c, 0x34, 0xe5, 0x3b, 0x45, 0x37, 0xf5, 0x3b, 0xe5, 0x3a, 0x45, 0x36, //0x8b60,
	0xf5, 0x3a, 0xe5, 0x39, 0x45, 0x35, 0xf5, 0x39, 0xe5, 0x38, 0x45, 0x34, 0xf5, 0x38, 0xe4, 0xf5, //0x8b70,
	0x22, 0xf5, 0x23, 0x85, 0x3b, 0x31, 0x85, 0x3a, 0x30, 0x85, 0x39, 0x2f, 0x85, 0x38, 0x2e, 0x02, //0x8b80,
	0x0f, 0x46, 0xe0, 0xa3, 0xe0, 0x75, 0xf0, 0x02, 0xa4, 0xff, 0xae, 0xf0, 0xc3, 0x08, 0xe6, 0x9f, //0x8b90,
	0xf6, 0x18, 0xe6, 0x9e, 0xf6, 0x22, 0xff, 0xe5, 0xf0, 0x34, 0x60, 0x8f, 0x82, 0xf5, 0x83, 0xec, //0x8ba0,
	0xf0, 0x22, 0x78, 0x52, 0x7e, 0x00, 0xe6, 0xfc, 0x08, 0xe6, 0xfd, 0x02, 0x04, 0xc1, 0xe4, 0xfc, //0x8bb0,
	0xfd, 0x12, 0x06, 0x99, 0x78, 0x5c, 0xe6, 0xc3, 0x13, 0xfe, 0x08, 0xe6, 0x13, 0x22, 0x78, 0x52, //0x8bc0,
	0xe6, 0xfe, 0x08, 0xe6, 0xff, 0xe4, 0xfc, 0xfd, 0x22, 0xe7, 0xc4, 0xf8, 0x54, 0xf0, 0xc8, 0x68, //0x8bd0,
	0xf7, 0x09, 0xe7, 0xc4, 0x54, 0x0f, 0x48, 0xf7, 0x22, 0xe6, 0xfc, 0xed, 0x75, 0xf0, 0x04, 0xa4, //0x8be0,
	0x22, 0x12, 0x06, 0x7c, 0x8f, 0x48, 0x8e, 0x47, 0x8d, 0x46, 0x8c, 0x45, 0x22, 0xe0, 0xfe, 0xa3, //0x8bf0,
	0xe0, 0xfd, 0xee, 0xf6, 0xed, 0x08, 0xf6, 0x22, 0x13, 0xff, 0xc3, 0xe6, 0x9f, 0xff, 0x18, 0xe6, //0x8c00,
	0x9e, 0xfe, 0x22, 0xe6, 0xc3, 0x13, 0xf7, 0x08, 0xe6, 0x13, 0x09, 0xf7, 0x22, 0xad, 0x39, 0xac, //0x8c10,
	0x38, 0xfa, 0xf9, 0xf8, 0x12, 0x05, 0x28, 0x8f, 0x3b, 0x8e, 0x3a, 0x8d, 0x39, 0x8c, 0x38, 0xab, //0x8c20,
	0x37, 0xaa, 0x36, 0xa9, 0x35, 0xa8, 0x34, 0x22, 0x93, 0xff, 0xe4, 0xfc, 0xfd, 0xfe, 0x12, 0x05, //0x8c30,
	0x28, 0x8f, 0x37, 0x8e, 0x36, 0x8d, 0x35, 0x8c, 0x34, 0x22, 0x78, 0x84, 0xe6, 0xfe, 0x08, 0xe6, //0x8c40,
	0xff, 0xe4, 0x8f, 0x37, 0x8e, 0x36, 0xf5, 0x35, 0xf5, 0x34, 0x22, 0x90, 0x0e, 0x8c, 0xe4, 0x93, //0x8c50,
	0x25, 0xe0, 0x24, 0x0a, 0xf8, 0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x22, 0xe6, 0xfe, 0x08, 0xe6, 0xff, //0x8c60,
	0xe4, 0x8f, 0x3b, 0x8e, 0x3a, 0xf5, 0x39, 0xf5, 0x38, 0x22, 0x78, 0x4e, 0xe6, 0xfe, 0x08, 0xe6, //0x8c70,
	0xff, 0x22, 0xef, 0x25, 0xe0, 0x24, 0x4e, 0xf8, 0xe6, 0xfc, 0x08, 0xe6, 0xfd, 0x22, 0x78, 0x89, //0x8c80,
	0xef, 0x26, 0xf6, 0x18, 0xe4, 0x36, 0xf6, 0x22, 0x75, 0x89, 0x03, 0x75, 0xa8, 0x01, 0x75, 0xb8, //0x8c90,
	0x04, 0x75, 0x34, 0xff, 0x75, 0x35, 0x0e, 0x75, 0x36, 0x15, 0x75, 0x37, 0x0d, 0x12, 0x0e, 0x9a, //0x8ca0,
	0x12, 0x00, 0x09, 0x12, 0x0f, 0x16, 0x12, 0x00, 0x06, 0xd2, 0x00, 0xd2, 0x34, 0xd2, 0xaf, 0x75, //0x8cb0,
	0x34, 0xff, 0x75, 0x35, 0x0e, 0x75, 0x36, 0x49, 0x75, 0x37, 0x03, 0x12, 0x0e, 0x9a, 0x30, 0x08, //0x8cc0,
	0x09, 0xc2, 0x34, 0x12, 0x08, 0xcb, 0xc2, 0x08, 0xd2, 0x34, 0x30, 0x0b, 0x09, 0xc2, 0x36, 0x12, //0x8cd0,
	0x02, 0x6c, 0xc2, 0x0b, 0xd2, 0x36, 0x30, 0x09, 0x09, 0xc2, 0x36, 0x12, 0x00, 0x0e, 0xc2, 0x09, //0x8ce0,
	0xd2, 0x36, 0x30, 0x0e, 0x03, 0x12, 0x06, 0xd7, 0x30, 0x35, 0xd3, 0x90, 0x30, 0x29, 0xe5, 0x1e, //0x8cf0,
	0xf0, 0xb4, 0x10, 0x05, 0x90, 0x30, 0x23, 0xe4, 0xf0, 0xc2, 0x35, 0x80, 0xc1, 0xe4, 0xf5, 0x4b, //0x8d00,
	0x90, 0x0e, 0x7a, 0x93, 0xff, 0xe4, 0x8f, 0x37, 0xf5, 0x36, 0xf5, 0x35, 0xf5, 0x34, 0xaf, 0x37, //0x8d10,
	0xae, 0x36, 0xad, 0x35, 0xac, 0x34, 0x90, 0x0e, 0x6a, 0x12, 0x0d, 0xf6, 0x8f, 0x37, 0x8e, 0x36, //0x8d20,
	0x8d, 0x35, 0x8c, 0x34, 0x90, 0x0e, 0x72, 0x12, 0x06, 0x7c, 0xef, 0x45, 0x37, 0xf5, 0x37, 0xee, //0x8d30,
	0x45, 0x36, 0xf5, 0x36, 0xed, 0x45, 0x35, 0xf5, 0x35, 0xec, 0x45, 0x34, 0xf5, 0x34, 0xe4, 0xf5, //0x8d40,
	0x22, 0xf5, 0x23, 0x85, 0x37, 0x31, 0x85, 0x36, 0x30, 0x85, 0x35, 0x2f, 0x85, 0x34, 0x2e, 0x12, //0x8d50,
	0x0f, 0x46, 0xe4, 0xf5, 0x22, 0xf5, 0x23, 0x90, 0x0e, 0x72, 0x12, 0x0d, 0xea, 0x12, 0x0f, 0x46, //0x8d60,
	0xe4, 0xf5, 0x22, 0xf5, 0x23, 0x90, 0x0e, 0x6e, 0x12, 0x0d, 0xea, 0x02, 0x0f, 0x46, 0xe5, 0x40, //0x8d70,
	0x24, 0xf2, 0xf5, 0x37, 0xe5, 0x3f, 0x34, 0x43, 0xf5, 0x36, 0xe5, 0x3e, 0x34, 0xa2, 0xf5, 0x35, //0x8d80,
	0xe5, 0x3d, 0x34, 0x28, 0xf5, 0x34, 0xe5, 0x37, 0xff, 0xe4, 0xfe, 0xfd, 0xfc, 0x78, 0x18, 0x12, //0x8d90,
	0x06, 0x69, 0x8f, 0x40, 0x8e, 0x3f, 0x8d, 0x3e, 0x8c, 0x3d, 0xe5, 0x37, 0x54, 0xa0, 0xff, 0xe5, //0x8da0,
	0x36, 0xfe, 0xe4, 0xfd, 0xfc, 0x78, 0x07, 0x12, 0x06, 0x56, 0x78, 0x10, 0x12, 0x0f, 0x9a, 0xe4, //0x8db0,
	0xff, 0xfe, 0xe5, 0x35, 0xfd, 0xe4, 0xfc, 0x78, 0x0e, 0x12, 0x06, 0x56, 0x12, 0x0f, 0x9d, 0xe4, //0x8dc0,
	0xff, 0xfe, 0xfd, 0xe5, 0x34, 0xfc, 0x78, 0x18, 0x12, 0x06, 0x56, 0x78, 0x08, 0x12, 0x0f, 0x9a, //0x8dd0,
	0x22, 0x8f, 0x3b, 0x8e, 0x3a, 0x8d, 0x39, 0x8c, 0x38, 0x22, 0x12, 0x06, 0x7c, 0x8f, 0x31, 0x8e, //0x8de0,
	0x30, 0x8d, 0x2f, 0x8c, 0x2e, 0x22, 0x93, 0xf9, 0xf8, 0x02, 0x06, 0x69, 0x00, 0x00, 0x00, 0x00, //0x8df0,
	0x12, 0x01, 0x17, 0x08, 0x31, 0x15, 0x53, 0x54, 0x44, 0x20, 0x20, 0x20, 0x20, 0x20, 0x13, 0x01, //0x8e00,
	0x10, 0x01, 0x56, 0x40, 0x1a, 0x30, 0x29, 0x7e, 0x00, 0x30, 0x04, 0x20, 0xdf, 0x30, 0x05, 0x40, //0x8e10,
	0xbf, 0x50, 0x03, 0x00, 0xfd, 0x50, 0x27, 0x01, 0xfe, 0x60, 0x00, 0x11, 0x00, 0x3f, 0x05, 0x30, //0x8e20,
	0x00, 0x3f, 0x06, 0x22, 0x00, 0x3f, 0x01, 0x2a, 0x00, 0x3f, 0x02, 0x00, 0x00, 0x36, 0x06, 0x07, //0x8e30,
	0x00, 0x3f, 0x0b, 0x0f, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x30, 0x01, 0x40, 0xbf, 0x30, 0x01, 0x00, //0x8e40,
	0xbf, 0x30, 0x29, 0x70, 0x00, 0x3a, 0x00, 0x00, 0xff, 0x3a, 0x00, 0x00, 0xff, 0x36, 0x03, 0x36, //0x8e50,
	0x02, 0x41, 0x44, 0x58, 0x20, 0x18, 0x10, 0x0a, 0x04, 0x04, 0x00, 0x03, 0xff, 0x64, 0x00, 0x00, //0x8e60,
	0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x04, 0x06, 0x06, 0x00, 0x03, 0x51, 0x00, 0x7a, //0x8e70,
	0x50, 0x3c, 0x28, 0x1e, 0x10, 0x10, 0x50, 0x2d, 0x28, 0x16, 0x10, 0x10, 0x02, 0x00, 0x10, 0x0c, //0x8e80,
	0x10, 0x04, 0x0c, 0x6e, 0x06, 0x05, 0x00, 0xa5, 0x5a, 0x00, 0xae, 0x35, 0xaf, 0x36, 0xe4, 0xfd, //0x8e90,
	0xed, 0xc3, 0x95, 0x37, 0x50, 0x33, 0x12, 0x0f, 0xe2, 0xe4, 0x93, 0xf5, 0x38, 0x74, 0x01, 0x93, //0x8ea0,
	0xf5, 0x39, 0x45, 0x38, 0x60, 0x23, 0x85, 0x39, 0x82, 0x85, 0x38, 0x83, 0xe0, 0xfc, 0x12, 0x0f, //0x8eb0,
	0xe2, 0x74, 0x03, 0x93, 0x52, 0x04, 0x12, 0x0f, 0xe2, 0x74, 0x02, 0x93, 0x42, 0x04, 0x85, 0x39, //0x8ec0,
	0x82, 0x85, 0x38, 0x83, 0xec, 0xf0, 0x0d, 0x80, 0xc7, 0x22, 0x78, 0xbe, 0xe6, 0xd3, 0x08, 0xff, //0x8ed0,
	0xe6, 0x64, 0x80, 0xf8, 0xef, 0x64, 0x80, 0x98, 0x22, 0x93, 0xff, 0x7e, 0x00, 0xe6, 0xfc, 0x08, //0x8ee0,
	0xe6, 0xfd, 0x12, 0x04, 0xc1, 0x78, 0xc1, 0xe6, 0xfc, 0x08, 0xe6, 0xfd, 0xd3, 0xef, 0x9d, 0xee, //0x8ef0,
	0x9c, 0x22, 0x78, 0xbd, 0xd3, 0xe6, 0x64, 0x80, 0x94, 0x80, 0x22, 0x25, 0xe0, 0x24, 0x0a, 0xf8, //0x8f00,
	0xe6, 0xfe, 0x08, 0xe6, 0xff, 0x22, 0xe5, 0x3c, 0xd3, 0x94, 0x00, 0x40, 0x0b, 0x90, 0x0e, 0x88, //0x8f10,
	0x12, 0x0b, 0xf1, 0x90, 0x0e, 0x86, 0x80, 0x09, 0x90, 0x0e, 0x82, 0x12, 0x0b, 0xf1, 0x90, 0x0e, //0x8f20,
	0x80, 0xe4, 0x93, 0xf5, 0x44, 0xa3, 0xe4, 0x93, 0xf5, 0x43, 0xd2, 0x06, 0x30, 0x06, 0x03, 0xd3, //0x8f30,
	0x80, 0x01, 0xc3, 0x92, 0x0e, 0x22, 0xa2, 0xaf, 0x92, 0x32, 0xc2, 0xaf, 0xe5, 0x23, 0x45, 0x22, //0x8f40,
	0x90, 0x0e, 0x5d, 0x60, 0x0e, 0x12, 0x0f, 0xcb, 0xe0, 0xf5, 0x2c, 0x12, 0x0f, 0xc8, 0xe0, 0xf5, //0x8f50,
	0x2d, 0x80, 0x0c, 0x12, 0x0f, 0xcb, 0xe5, 0x30, 0xf0, 0x12, 0x0f, 0xc8, 0xe5, 0x31, 0xf0, 0xa2, //0x8f60,
	0x32, 0x92, 0xaf, 0x22, 0xd2, 0x01, 0xc2, 0x02, 0xe4, 0xf5, 0x1f, 0xf5, 0x1e, 0xd2, 0x35, 0xd2, //0x8f70,
	0x33, 0xd2, 0x36, 0xd2, 0x01, 0xc2, 0x02, 0xf5, 0x1f, 0xf5, 0x1e, 0xd2, 0x35, 0xd2, 0x33, 0x22, //0x8f80,
	0xfb, 0xd3, 0xed, 0x9b, 0x74, 0x80, 0xf8, 0x6c, 0x98, 0x22, 0x12, 0x06, 0x69, 0xe5, 0x40, 0x2f, //0x8f90,
	0xf5, 0x40, 0xe5, 0x3f, 0x3e, 0xf5, 0x3f, 0xe5, 0x3e, 0x3d, 0xf5, 0x3e, 0xe5, 0x3d, 0x3c, 0xf5, //0x8fa0,
	0x3d, 0x22, 0xc0, 0xe0, 0xc0, 0x83, 0xc0, 0x82, 0x90, 0x3f, 0x0d, 0xe0, 0xf5, 0x33, 0xe5, 0x33, //0x8fb0,
	0xf0, 0xd0, 0x82, 0xd0, 0x83, 0xd0, 0xe0, 0x32, 0x90, 0x0e, 0x5f, 0xe4, 0x93, 0xfe, 0x74, 0x01, //0x8fc0,
	0x93, 0xf5, 0x82, 0x8e, 0x83, 0x22, 0x78, 0x7f, 0xe4, 0xf6, 0xd8, 0xfd, 0x75, 0x81, 0xcd, 0x02, //0x8fd0,
	0x0c, 0x98, 0x8f, 0x82, 0x8e, 0x83, 0x75, 0xf0, 0x04, 0xed, 0x02, 0x06, 0xa5, //0x8fe0
};

static int ov5640_sensor_read(struct v4l2_subdev *sd, unsigned char *reg,
		unsigned char *value)
{
	struct i2c_client *client = v4l2_get_subdevdata(sd);
	u8 data[REG_STEP];
	struct i2c_msg msg;
	int ret,i;
	
	for(i = 0; i < REG_ADDR_STEP; i++)
		data[i] = reg[i];
	
	for(i = REG_ADDR_STEP; i < REG_STEP; i++)
		data[i] = 0xff;
	/*
	 * Send out the register address...
	 */
	msg.addr = client->addr;
	msg.flags = 0;
	msg.len = REG_ADDR_STEP;
	msg.buf = data;
	ret = i2c_transfer(client->adapter, &msg, 1);
	if (ret < 0) {
		csi_dev_err("Error %d on register write\n", ret);
		return ret;
	}
	/*
	 * ...then read back the result.
	 */
	
	msg.flags = I2C_M_RD;
	msg.len = REG_DATA_STEP;
	msg.buf = &data[REG_ADDR_STEP];
	
	ret = i2c_transfer(client->adapter, &msg, 1);
	if (ret >= 0) {
		for(i = 0; i < REG_DATA_STEP; i++)
			value[i] = data[i+REG_ADDR_STEP];
		ret = 0;
	}
	else {
		csi_dev_err("Error %d on register read\n", ret);
	}
	return ret;
}

static int ov5640_sensor_write(struct v4l2_subdev *sd, unsigned char *reg,
		unsigned char *value)
{
	struct i2c_client *client = v4l2_get_subdevdata(sd);
	struct i2c_msg msg;
	unsigned char data[REG_STEP];
	int ret,i;
	
	for(i = 0; i < REG_ADDR_STEP; i++)
			data[i] = reg[i];
	for(i = REG_ADDR_STEP; i < REG_STEP; i++)
			data[i] = value[i-REG_ADDR_STEP];
	
	msg.addr = client->addr;
	msg.flags = 0;
	msg.len = REG_STEP;
	msg.buf = data;

	
	ret = i2c_transfer(client->adapter, &msg, 1);
	if (ret > 0) {
		ret = 0;
	}
	else if (ret < 0) {
		csi_dev_print("addr = 0x%4x, value = 0x%2x\n ",reg[0]*256+reg[1],value[0]);
		csi_dev_err("sensor_write error!\n");
	}
	return ret;
}

#if 0
static int sensor_write_im(struct v4l2_subdev *sd, unsigned int addr,
		unsigned char value)
{
	struct i2c_client *client = v4l2_get_subdevdata(sd);
	struct i2c_msg msg;
	unsigned char data[REG_STEP];
	int ret;
	unsigned int retry=0;
	
	data[0] = (addr&0xff00)>>8;
	data[1] = addr&0x00ff;
	data[2] = value;
	
	msg.addr = client->addr;
	msg.flags = 0;
	msg.len = REG_STEP;
	msg.buf = data;

sensor_write_im_transfer:
	ret = i2c_transfer(client->adapter, &msg, 1);
	if (ret > 0) {
		ret = 0;
	}
	else if (ret < 0) {
		if(retry<3) {
			retry++;
			csi_dev_err("sensor_write retry %d!\n",retry);
			goto sensor_write_im_transfer;
		}
		
		csi_dev_err("addr = 0x%4x, value = 0x%4x\n ",addr,value);
		csi_dev_err("sensor_write error!\n");
	}
	return ret;
}
#endif

static int ov5640_sensor_write_array(struct v4l2_subdev *sd, struct regval_list *vals , uint size)
{
	int i,ret;
	unsigned int cnt;
//	unsigned char rd;
	if (size == 0)
		return -EINVAL;

	for(i = 0; i < size ; i++)
	{
		if(vals->reg_num[0] == 0xff && vals->reg_num[1] == 0xff) {
			mdelay(vals->value[0]);
		}	
		else {
			cnt=0;
			ret = ov5640_sensor_write(sd, vals->reg_num, vals->value);
			while( ret < 0 && cnt < 3)
			{
				if(ret<0)
					csi_dev_err("sensor_write_err!\n");
				ret = ov5640_sensor_write(sd, vals->reg_num, vals->value);
				cnt++;
			}
			if(cnt>0)
				csi_dev_err("csi i2c retry cnt=%d\n",cnt);
			
			if(ret<0 && cnt >=3)
				return ret;
		}
		vals++;
	}
	
	return 0;
}

static int ov5640_sensor_write_continuous(struct v4l2_subdev *sd, int addr, char vals[] , uint size)
{
	int i,ret;
	struct regval_list reg_addr;
	
	if (size == 0)
		return -EINVAL;
	
	for(i = 0; i < size ; i++)
	{
		reg_addr.reg_num[0] = (addr&0xff00)>>8;
		reg_addr.reg_num[1] = (addr&0x00ff);
		
		ret = ov5640_sensor_write(sd, reg_addr.reg_num, &vals[i]);
		if (ret < 0)
		{
			csi_dev_err("sensor_write_err!\n");
			return ret;
		}
		addr++;
	}
	
	return 0;
}

/* stuff about auto focus */
static int ov5640_sensor_download_af_fw(struct v4l2_subdev *sd)
{
	int ret,cnt;
	struct regval_list regs;
	struct regval_list af_fw_reset_reg[] = {
		{{0x30,0x00},{0x20}},
	};
	struct regval_list af_fw_start_reg[] = {
		{{0x30,0x22},{0x00}},
		{{0x30,0x23},{0x00}},
		{{0x30,0x24},{0x00}},
		{{0x30,0x25},{0x00}},
		{{0x30,0x26},{0x00}},
		{{0x30,0x27},{0x00}},
		{{0x30,0x28},{0x00}},
		{{0x30,0x29},{0x7f}},//0x7f
		{{0x30,0x00},{0x00}},	//start firmware for af
	};

	//reset sensor MCU
	ret = ov5640_sensor_write_array(sd, af_fw_reset_reg, ARRAY_SIZE(af_fw_reset_reg));
	if(ret < 0) {
		csi_dev_err("reset sensor MCU error\n");
		return ret;
	}
		
	//download af fw
	ret =ov5640_sensor_write_continuous(sd, 0x8000, ov5640_sensor_af_fw_regs, ARRAY_SIZE(ov5640_sensor_af_fw_regs));
	if(ret < 0) {
		csi_dev_err("download af fw error\n");
		return ret;
	}
	//start af firmware
	ret = ov5640_sensor_write_array(sd, af_fw_start_reg, ARRAY_SIZE(af_fw_start_reg));
	if(ret < 0) {
		csi_dev_err("start af firmware error\n");
		return ret;
	}
	
	mdelay(10);
	//check the af firmware status
	regs.reg_num[0] = 0x30;
	regs.reg_num[1] = 0x29;
	regs.value[0] = 0xff;
	cnt = 0;
	while(regs.value[0]!=0x70) {
		mdelay(5);
		ret = ov5640_sensor_read(sd, regs.reg_num, regs.value);
		if (ret < 0)
		{
			csi_dev_err("sensor check the af firmware status err !\n");
			return ret;
		}
		cnt++;
		if(cnt > 200) {
			csi_dev_err("AF firmware check status time out !\n");
			return -EFAULT;
		}
	}
	csi_dev_print("AF firmware check status complete,0x3029 = 0x%x\n",regs.value[0]);

#if DEV_DBG_EN == 1	
	regs.reg_num[0] = 0x30;
	regs.reg_num[1] = 0x00;
	ov5640_sensor_read(sd, regs.reg_num, regs.value);
	csi_dev_print("0x3000 = 0x%x\n",regs.value[0]);
	
	regs.reg_num[0] = 0x30;
	regs.reg_num[1] = 0x04;
	ov5640_sensor_read(sd, regs.reg_num, regs.value);
	csi_dev_print("0x3004 = 0x%x\n",regs.value[0]);
	
	regs.reg_num[0] = 0x30;
	regs.reg_num[1] = 0x01;
	ov5640_sensor_read(sd, regs.reg_num, regs.value);
	csi_dev_print("0x3001 = 0x%x\n",regs.value[0]);

	regs.reg_num[0] = 0x30;
	regs.reg_num[1] = 0x05;
	ov5640_sensor_read(sd, regs.reg_num, regs.value);
	csi_dev_print("0x3005 = 0x%x\n",regs.value[0]);
#endif

  return 0;
}

static int ov5640_sensor_s_release_af(struct v4l2_subdev *sd)
{
	struct regval_list regs;
	int ret;
	//release focus
	csi_dev_print("sensor_s_release_af\n");
	
	//trig single af
	regs.reg_num[0] = 0x30;
	regs.reg_num[1] = 0x22;
	regs.value[0] = 0x03;	
	ret = ov5640_sensor_write(sd, regs.reg_num, regs.value);
	if (ret < 0)
	{
		csi_dev_err("sensor tigger single af err !\n");
		return ret;
	}
	//release single af
	regs.reg_num[0] = 0x30;
	regs.reg_num[1] = 0x22;
	regs.value[0] = 0x08;	
	ret = ov5640_sensor_write(sd, regs.reg_num, regs.value);
	if (ret < 0)
	{
		csi_dev_err("release focus err !\n");
		return ret;
	}
	return 0;
}

static int ov5640_sensor_s_af_zone(struct v4l2_subdev *sd, unsigned int xc, unsigned int yc)
{
	//struct sensor_info *info = to_state(sd);
	struct regval_list regs;
	int ret;
	
	csi_dev_print("sensor_s_af_zone\n");
	csi_dev_print("af zone input xc=%d,yc=%d\n",xc,yc);
#if 0	
	if(info->width == 0 || info->height == 0) {
		csi_dev_err("current width or height is zero!\n");
		return -EINVAL;
	}
#endif	
	xc = xc * 80 /640;
	
	yc = yc * 60 / 480;
	
	
	//csi_dev_dbg("af zone after xc=%d,yc=%d\n",xc,yc);
		
	//set x center
	regs.reg_num[0] = 0x30;
	regs.reg_num[1] = 0x24;
	regs.value[0] = xc;	
	ret = ov5640_sensor_write(sd, regs.reg_num, regs.value);
	if (ret < 0)
	{
		csi_dev_err("sensor_s_af_zone_xc error!\n");
		return ret;
	}
	//set y center
	regs.reg_num[0] = 0x30;
	regs.reg_num[1] = 0x25;
	regs.value[0] = yc;	
	ret = ov5640_sensor_write(sd, regs.reg_num, regs.value);
	if (ret < 0)
	{
		csi_dev_err("sensor_s_af_zone_yc error!\n");
		return ret;
	}
	
	//set af zone
	regs.reg_num[0] = 0x30;
	regs.reg_num[1] = 0x22;
	regs.value[0] = 0x81;	
	ret = ov5640_sensor_write(sd, regs.reg_num, regs.value);
	if (ret < 0)
	{
		csi_dev_err("sensor_s_af_zone error!\n");
		return ret;
	}
	mdelay(5);
	return 0;
}

static int ov5640_sensor_s_pause_af(struct v4l2_subdev *sd)
{
	struct regval_list regs;
	int ret;
	//pause af poisition
	csi_dev_print("sensor_s_pause_af\n");
	regs.reg_num[0] = 0x30;
	regs.reg_num[1] = 0x22;
	regs.value[0] = 0x06;	
	ret = ov5640_sensor_write(sd, regs.reg_num, regs.value);
	if (ret < 0)
	{
		csi_dev_err("sensor pause af err !\n");
		return ret;
	}
	mdelay(5);
	return 0;
}

static int ov5640_get_auto_focus_result(struct v4l2_subdev *sd,
					struct v4l2_control *ctrl)
{
	struct regval_list regs;
	int ret,cnt;

	regs.reg_num[0] = 0x30;
	regs.reg_num[1] = 0x23;
	regs.value[0] = 0xff;
	cnt = 0;


        //dg add  2015-07-13 0x3022 register:

       // 0x03 - Trig Single Auto Focus
       // 0x06 - Pause Auto Focus
       // 0x08 - Release Focus
       // 0x12 - Re-launch Focus Zones
       // 0x00 – command is finished

        //send idle command to firmware

        OV5640YUV_write_cmos_sensor(0x3023,0x01);
        OV5640YUV_write_cmos_sensor(0x3022,0x06); //pause auto focus


        //wait for af pause complete
        regs.reg_num[0] = 0x30;
        regs.reg_num[1] = 0x29;//dg change 0x23 to 0x29;
        regs.value[0] = 0xff;
         cnt = 0;
        while(regs.value[0]!=0x10)// dg change 0x00 to 0x10
        {
                mdelay(50);
                ret = ov5640_sensor_read(sd, regs.reg_num, regs.value);
                if (ret < 0)
                {
                        csi_dev_err("sensor get af pause status err !\n");
                        return ret;
                }
                cnt++;
                if(cnt>1000) {
                        csi_dev_err("Single AF  pause is timeout,value = 0x%x\n",regs.value[0]);
                        return -EFAULT;
                }
        }


        printk("pause focus  ok.....................");

	//ov5640_sensor_s_af_zone(sd, 640, 480);

        ctrl->value = AUTO_FOCUS_DONE;

	return 0;
}

static int ov5640_sensor_s_single_af(struct v4l2_subdev *sd)
{
	struct regval_list regs;
	int ret;
	csi_dev_print("sensor_s_single_af\n");
#if 1
	//trig single af
	regs.reg_num[0] = 0x30;
	regs.reg_num[1] = 0x23;
	regs.value[0] = 0x01;	
	ret = ov5640_sensor_write(sd, regs.reg_num, regs.value);
	if (ret < 0)
	{
		csi_dev_err("sensor tigger single af err !\n");
		return ret;
	}
#endif
	regs.reg_num[0] = 0x30;
	regs.reg_num[1] = 0x22;
	regs.value[0] = 0x03;	
	ret = ov5640_sensor_write(sd, regs.reg_num, regs.value);
	if (ret < 0)
	{
		csi_dev_err("sensor tigger single af err !\n");
		return ret;
	}
#if 1
	//wait for af complete
	regs.reg_num[0] = 0x30;
        regs.reg_num[1] = 0x29;//dg change 0x23 to 0x29;
	regs.value[0] = 0xff;
        int cnt = 0;
        while(regs.value[0]!=0x10)// dg change 0x00 to 0x10)
	{
                mdelay(50);
		ret = ov5640_sensor_read(sd, regs.reg_num, regs.value);
		if (ret < 0)
		{
			csi_dev_err("sensor get af status err !\n");
			return ret;
		}
		cnt++;
                if(cnt>100) {
			csi_dev_err("Single AF is timeout,value = 0x%x\n",regs.value[0]);
			return -EFAULT;
		}
	}
#else
	;
#endif

        csi_dev_print("Single AF is complete,value = 0x%x\n",regs.value[0]);

  return 0;
}
/* end add */



static inline struct ov5640_priv *to_ov5640(const struct i2c_client *client)
{
	return container_of(i2c_get_clientdata(client), struct ov5640_priv, subdev);
}


static int write_regs(struct i2c_client *client, 
    const struct regval *regs, int array_len)
{
    int i;
    int ret = 0;

    for (i = 0; i < array_len; i++) {
        if ((ret = i2cc_set_reg(client, regs->reg, regs->val))) {
            OV_ERR("error to set reg:0x%d -> value:%d(index:%d)\n", regs->reg, 
                regs->val, i);
            break;
        }
        regs++;
    }

//    INFO_BLUE("------*------- write array regs over -------*------ \n");

    return (ret);
}


static int ov5640_set_bus_param(struct soc_camera_device *icd, 
    unsigned long flags)
{
    INFO_PURLPLE("\n");
	return 0;
}

static unsigned long ov5640_query_bus_param(struct soc_camera_device *icd)
{
	struct soc_camera_link *icl = to_soc_camera_link(icd);
    
    /* camera can do 10 bit transfers,  but omit it now */
	unsigned long flags = SOCAM_PCLK_SAMPLE_RISING | SOCAM_MASTER |
		SOCAM_VSYNC_ACTIVE_HIGH | SOCAM_HSYNC_ACTIVE_HIGH |
		SOCAM_DATA_ACTIVE_HIGH | SOCAM_DATAWIDTH_8;

	return soc_camera_apply_sensor_flags(icl, flags);
}


static int ov5640_g_chip_ident(struct v4l2_subdev *sd,
			       struct v4l2_dbg_chip_ident *id)
{
	struct i2c_client *client = v4l2_get_subdevdata(sd);
	struct ov5640_priv *priv = to_ov5640(client);

	id->ident = priv->model;
	id->revision = 0;

	return (0);
}


static const struct ov5640_win_size *select_win(
    unsigned int width, unsigned int height)
{
    const struct ov5640_win_size *ret = NULL;
    int size = ARRAY_SIZE(ov5640_wins);
    unsigned int diff = -1;
    unsigned int tmp;
    int i;

	//width = 1600;
	//height = 1200;

    for (i = 0; i < size; i++) {
        tmp = abs(width - ov5640_wins[i].width) + 
            abs(height - ov5640_wins[i].height);
        if (tmp < diff) {
            diff = tmp;
            ret = ov5640_wins + i;
        }
    }
    return (ret); 
}


static int ov5640_try_fmt(struct v4l2_subdev *sd,
    struct v4l2_mbus_framefmt *vmf)
{
    struct i2c_client *client = v4l2_get_subdevdata(sd);
    struct ov5640_priv *priv = to_ov5640(client);
    const struct ov5640_win_size *win;
    int found = 0;
    int i;

    
    win = select_win(vmf->width, vmf->height);
    vmf->width = win->width;
    vmf->height = win->height;
    vmf->field = V4L2_FIELD_NONE;

    for (i = 0; i < ARRAY_SIZE(ov5640_cfmts); i++) {
        if (ov5640_cfmts[i].code == vmf->code) {
            found = 1;
            break;
        }
    }

    if (found) {
        vmf->colorspace = ov5640_cfmts[i].colorspace;
    } else {
        /* Unsupported format requested. Propose either */
		if (priv->cfmt) {
			/* the current one or */
			vmf->colorspace = priv->cfmt->colorspace;
			vmf->code = priv->cfmt->code;
		} else {
			/* the default one */
			vmf->colorspace = ov5640_cfmts[0].colorspace;
			vmf->code = ov5640_cfmts[0].code;
		}
    }

    INFO_GREEN("code:%d-%s %dX%d\n", 
        vmf->code, win->name, vmf->width, vmf->height);

    return (0);
}



/* start or stop streaming from the device */
static int ov5640_s_stream(struct v4l2_subdev *sd, int enable)
{
    struct i2c_client *client = v4l2_get_subdevdata(sd);
    struct ov5640_priv *priv = to_ov5640(client);

    if (!enable) {
        INFO_PURLPLE("stream down\n");
        // set regs to enter sleep mode, already in DVP mode
     //   i2cc_set_reg(client, 0x3008, 0x42); //dg cancel 2015-07-18,  ov5640 power down,beacuse it cause some command not running.
        return (0);
    }
#if 0
    if (NULL == priv->win || NULL == priv->cfmt) {
        OV_ERR("win or cfmt select error!\n");
        return (-EPERM);
    }
#endif


    INFO_PURLPLE("stream on\n");
    //set regs to leave sleep mode, in DVP mode , needn't to set 0x300e to 0xc
  //  i2cc_set_reg(client, 0x3008, 0x02);  //dg cancel 2015-07-18,//dg cancel 2015-07-18,  ov5640 power down,beacuse it cause some command not running.
    
#if 0
    INFO_GREEN("format: %d, win:%s\n", priv->cfmt->code, priv->win->name);

    // wait for 2 Vsync, and capture the 3rd frame, (1 / 7.5) * 2 =. 267ms
    mdelay(270);

	if(0 == down_af_firmware_flag)
	{
		ov5640_sensor_download_af_fw(sd);

		down_af_firmware_flag = 1;
	}

#endif
        OV5640YUVPreview();

       // OV5640YUVCapture();

        //ov5640_sensor_s_single_af(sd);
	
        //dg add 2015-07-15
        //OV5640_FOCUS_AD5820_Single_Focus();

    //    OV5640_FOCUS_AD5820_Constant_Focus();





    return (0);
}

static int reset_ov5640(struct i2c_client *client)
{
	int ret = i2cc_set_reg(client, 0x3008, 0x82);
	mdelay(5);
	return (ret);
}

#if 0  //remove by cym 20130807
static int ov5640_get_params(struct i2c_client *client, unsigned int *width, 
    unsigned int *height, enum v4l2_mbus_pixelcode code)
{
    struct ov5640_priv *priv = to_ov5640(client);
    int ret = -EINVAL;
    int i;

    /* select format */
    priv->cfmt = NULL;
    for (i = 0; i < ARRAY_SIZE(ov5640_cfmts); i++) {
        if (code == ov5640_cfmts[i].code) {
            priv->cfmt = ov5640_cfmts + i;
            break;
        }
    }
    if (NULL == priv->cfmt) {
        return (ret);
    }

    priv->win = select_win(*width, *height);

    *width = priv->win->width;
    *height = priv->win->height;

    INFO_PURLPLE("current params: %s %dX%d\n", 
        priv->win->name, *width, *height);

    return (0);
}
#endif

static inline void init_setting_values(struct ov5640_priv *priv)
{
    priv->flip_flag = OV5640_HFLIP; 
}

#if 1  //remove by cym 20130807
static void get_preview_params(struct i2c_client *client, 
    unsigned int *exposure, unsigned short *maxlines, unsigned short *gain)
{
    unsigned char ret_h = 0;
    unsigned char ret_m = 0;
    unsigned char ret_l = 0;

    i2cc_get_reg(client, 0x3500, &ret_h);
    i2cc_get_reg(client, 0x3501, &ret_m);
    i2cc_get_reg(client, 0x3502, &ret_l);
    *exposure = ((ret_h << 16) + (ret_m << 8) + ret_l) >> 4;
    INFO_GREEN("expl:0x%x, expm:0x%x, exph:0x%x\n", 
            ret_l, ret_m, ret_h);

    i2cc_get_reg(client, 0x350c, &ret_h);
    i2cc_get_reg(client, 0x350d, &ret_l);
    *maxlines = (ret_h << 8) + ret_l;

    //i2cc_get_reg(client, 0x350a, &ret_h);
    i2cc_get_reg(client, 0x350b, &ret_l);
    *gain = /*((ret_h & 0x1) << 8) + */ret_l;

    INFO_GREEN("exposure:0x%x, maxlines:0x%x, gain:0x%x\n",
        *exposure, *maxlines, *gain);
}
#endif

#if 1  //remove by cym 20130807
static void manual_set_exposure_and_gain(struct i2c_client *client,
    unsigned int p_exposure, unsigned short p_maxlines, unsigned short p_gain)
{
    unsigned char ret_h = 0;
    unsigned char ret_l = 0;
    unsigned char exp_h;
    unsigned char exp_m;
    unsigned char exp_l;
    unsigned char lines_10ms;
    unsigned short cap_maxlines;
    unsigned short cap_exposure;
    unsigned short cap_gain;
//    unsigned short gain;
    unsigned int   cap_exp_gain;

    i2cc_get_reg(client, 0x350c, &ret_h);
    i2cc_get_reg(client, 0x350d, &ret_l);
    cap_maxlines = (ret_h << 8) + ret_l;

    //p_maxlines = 980;
    //cap_maxlines = 1964;
    INFO_GREEN("cap_maxlines: 0x%x\n", cap_maxlines);
    
    // for 50HZ, if 60HZ, devided by 12000
    lines_10ms = CAPTURE_FRAME_RATE * cap_maxlines / 10000 * 13 / 12;

    if (0 == p_maxlines) {
        p_maxlines = 1;
    }


    cap_exposure = ((p_exposure * CAPTURE_FRAME_RATE * cap_maxlines) / 
        (p_maxlines * PREVIEW_FRAME_RATE)) * 6 / 5;

    //cap_exp_gain = 1126 * cap_exposure * cap_gain;
    cap_exp_gain = cap_exposure * p_gain;  // in night mode, need multiply 2 again.
    //cap_exp_gain >>= 9;
    if (cap_exp_gain < (long)cap_maxlines * 16) {
        cap_exposure = cap_exp_gain / 16;
        if (cap_exposure > lines_10ms) {
            cap_exposure /= lines_10ms;
            cap_exposure *= lines_10ms;
        }
    } else {
        cap_exposure = cap_maxlines;
    }

    if (0 == cap_exposure) {
        cap_exposure = 1;
    }

    cap_gain = ((cap_exp_gain << 1) / cap_exposure + 1) >> 1;

    exp_l = (cap_exposure << 4) & 0xFF;
    exp_m = (cap_exposure >> 4) & 0xFF;
    exp_h = (cap_exposure >> 12) & 0xFF;

    INFO_GREEN("gain:0x%x, expl:0x%x, expm:0x%x, exph:0x%x, cap_maxlines:0x%x\n", 
        cap_gain, exp_l, exp_m, exp_h, cap_maxlines);
    
    i2cc_set_reg(client, 0x350b, cap_gain);
    i2cc_set_reg(client, 0x3502, exp_l);
    i2cc_set_reg(client, 0x3501, exp_m);
    i2cc_set_reg(client, 0x3500, exp_h);

    /*
    * add delay-time, to avoid boundary problem between dark and bright
    */
    mdelay(100);
}
#endif

static int ov5640_set_params(struct i2c_client *client, unsigned int *width, 
    unsigned int *height, enum v4l2_mbus_pixelcode code)
{
    struct ov5640_priv *priv = to_ov5640(client);
    int ret = -EINVAL;
    int i;
    const struct regval *reg_list = NULL;
    int list_len = 0;

	printk("%s(%d): code = %d\n", __FUNCTION__, __LINE__, code);

	printk("%s(%d): width = %d, height = %d\n", __FUNCTION__, __LINE__, *width, *height);
	
    /* select format */
    priv->cfmt = NULL;
    for (i = 0; i < ARRAY_SIZE(ov5640_cfmts); i++) {
        if (code == ov5640_cfmts[i].code) {
            priv->cfmt = ov5640_cfmts + i;
            break;
        }
    }
    if (NULL == priv->cfmt) {
	printk("%s(%d)\n", __FUNCTION__, __LINE__);
        return (ret);
    }

    /* select win size, now only one, so select directly */
    priv->win = select_win(*width, *height);

    /* set hardware regs needed */
    if (RESV_VGA == priv->win->resv) {
        reset_ov5640(client);

        /* set default regs */
        write_regs(client, ov5640_init_regs, ARRAY_SIZE(ov5640_init_regs));
        init_setting_values(priv);
    }

    switch (priv->win->resv) {
        case RESV_XGA: {
            reg_list = ov5640_qsxga_to_xga_regs;
            list_len = ARRAY_SIZE(ov5640_qsxga_to_xga_regs);
            break;
        }
        case RESV_SXGA: {
            reg_list = ov5640_qsxga_to_sxga_regs;
            list_len = ARRAY_SIZE(ov5640_qsxga_to_sxga_regs);
            break;
        }
        case RESV_UXGA: {
            reg_list = ov5640_qsxga_to_uxga_regs;
            list_len = ARRAY_SIZE(ov5640_qsxga_to_uxga_regs);
            break;
        }
        case RESV_QXGA: {
            reg_list = ov5640_qsxga_to_qxga_regs;
            list_len = ARRAY_SIZE(ov5640_qsxga_to_qxga_regs);
            break;
        }
        case RESV_QSXGA:
        default:
            break;

    }
#if 0	//remove by cym 20130807
    if (RESV_VGA != priv->win->resv) {

        unsigned int preview_exp;
        unsigned short preview_maxl;
        unsigned short preview_gain;

        /* manually set exposure and gain */
       // i2cc_set_reg(client, 0x3503, 0x07);
        
        get_preview_params(client, &preview_exp, &preview_maxl, &preview_gain);

        write_regs(client, ov5640_qsxga_regs, ARRAY_SIZE(ov5640_qsxga_regs));
	write_regs(client, ov5640_qsxga_to_uxga_regs, ARRAY_SIZE(ov5640_qsxga_to_uxga_regs));

        if (NULL != reg_list) {
            ;//write_regs(client, reg_list, list_len);
        }

        //manual_set_exposure_and_gain(client, preview_exp, preview_maxl, preview_gain);
        

    }
#endif
    *width = priv->win->width;
    *height = priv->win->height;

    INFO_PURLPLE("ok, params are width:%d-height:%d\n", *width, *height);

    return (0);
}



static int ov5640_g_fmt(struct v4l2_subdev *sd, 
    struct v4l2_mbus_framefmt *vmf)
{
    struct i2c_client *client = v4l2_get_subdevdata(sd);
//    struct ov5640_priv *priv = to_ov5640(client);

	struct soc_camera_device *icd = client->dev.platform_data;

#if 0
    if (NULL == priv->win || NULL == priv->cfmt) {
        unsigned int width = VGA_WIDTH;
        unsigned int height = VGA_HEIGHT;
        int ret = 0;

        ret = ov5640_get_params(client, &width, &height, 2);
            //cym V4L2_MBUS_FMT_YUYV8_2X8_BE);
        if (ret < 0) {
            return (ret);
        }
    }

    vmf->width = priv->win->width;
    vmf->height = priv->win->height;
    vmf->code = priv->cfmt->code;
    vmf->colorspace = priv->cfmt->colorspace;
    vmf->field = V4L2_FIELD_NONE;
#else
	//printk("%s(%d)\n", __FUNCTION__, __LINE__);
	vmf->width	= icd->user_width;
	//printk("%s(%d)\n", __FUNCTION__, __LINE__);
	vmf->height	= icd->user_height;
	//printk("%s(%d)\n", __FUNCTION__, __LINE__);
	vmf->code	= 2;//priv->cfmt->code;
	//printk("%s(%d)\n", __FUNCTION__, __LINE__);
	vmf->colorspace	= V4L2_COLORSPACE_JPEG;//priv->cfmt->colorspace;
	vmf->field	= V4L2_FIELD_NONE;
#endif
    INFO_GREEN("ok, get fmt w:%dXh:%d-code:%d-csp:%d\n", 
        vmf->width, vmf->height, vmf->code, vmf->colorspace);

    return (0);
}


static int ov5640_s_fmt(struct v4l2_subdev *sd,
			struct v4l2_mbus_framefmt *vmf)
{
	struct i2c_client *client = v4l2_get_subdevdata(sd);
	struct ov5640_priv *priv = to_ov5640(client);

	//ov5640_g_fmt(sd, vmf);

	//printk("*********** %s, line = %d(code = 0x%x, w:%d, h:%d)\n", __FUNCTION__, __LINE__, 
	//						vmf->code, vmf->width, vmf->height);


#if 0
        int ret = ov5640_set_params(client, &vmf->width, &vmf->height, vmf->code);
        printk("%s(%d): rest = %d\n", __FUNCTION__, __LINE__, ret);
        if (!ret)
                vmf->colorspace = priv->cfmt->colorspace;

        return (ret);

#endif


        return 1;

    //INFO_PURLPLE("\n");


}


//  TODO..... modify
static int ov5640_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *vcc)
{
	vcc->bounds.left = OV5640_COLUMN_SKIP;
	vcc->bounds.top  = OV5640_ROW_SKIP;
	vcc->bounds.width  = OV5640_MAX_WIDTH;
	vcc->bounds.height = OV5640_MAX_HEIGHT;
	vcc->defrect = vcc->bounds;  /* set default rect. */
	vcc->type    = V4L2_BUF_TYPE_VIDEO_CAPTURE;
	vcc->pixelaspect.numerator   = 1;
	vcc->pixelaspect.denominator = 1;

    INFO_PURLPLE("\n");

	return (0);
}


//  TODO..... modify
static int ov5640_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *vc)
{
	vc->c.left	= 0;
	vc->c.top	= 0;
	vc->c.width	= QSXGA_WIDTH;
	vc->c.height	= QSXGA_HEIGHT;
	vc->type		= V4L2_BUF_TYPE_VIDEO_CAPTURE;

    INFO_BLUE("\n");

	return (0);
}


static int ov5640_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
			   enum v4l2_mbus_pixelcode *code)
{
	if (index >= ARRAY_SIZE(ov5640_cfmts))
		return -EINVAL;

	*code = ov5640_cfmts[index].code;
    OV_INFO("fmt index:%d\n", index);
	return 0;
}

static int ov5640_enum_framesizes(struct v4l2_subdev *sd,
				  struct v4l2_frmsizeenum *fsize)
{
	//struct s5k4ecgx_state *state =
	//	container_of(sd, struct s5k4ecgx_state, sd);
	//struct i2c_client *client = v4l2_get_subdevdata(sd);
	//struct ov5640_priv *priv = to_ov5640(client);
	
	//printk("********************** %s(%d) **************************\n", __FUNCTION__, __LINE__);
	
	fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
	fsize->discrete.width = 640;//state->pix.width;
	fsize->discrete.height = 480;//state->pix.height;
	return 0;
}

static int ov5640_set_brightness(struct i2c_client *client, int bright)
{
    struct ov5640_priv *priv = to_ov5640(client);
    unsigned char reg5587, reg5588;

    if (bright < -4 || 4 < bright) {
        OV_ERR("brightness - %d is out of range[-4, 4]\n", bright);
        return (-ERANGE);
    }

    if (bright < 0) {
        reg5587 = 0x10 * (-bright);
        reg5588 = 0x09; /* bit[3] is Y bright sign */
    } else {
        reg5587 = 0x10 * bright;
        reg5588 = 0x01;
    }

    i2cc_set_reg(client, 0x5001, 0xff);
    i2cc_set_reg(client, 0x5587, reg5587);
    i2cc_set_reg(client, 0x5580, 0x04);
    i2cc_set_reg(client, 0x5588, reg5588);
    priv->brightness = bright;
    OV_INFO("brightness:%d, reg5587:0x%x, reg5588:0x%x\n", 
        bright, reg5587, reg5588);
    return (0);
}


static int ov5640_set_contrast(struct i2c_client *client, int contrast)
{
    struct ov5640_priv *priv = to_ov5640(client);
    unsigned char y_gain, reg5588;

    if (contrast < -4 || 4 < contrast) {
        OV_ERR("contrast - %d is out of range[-4, 4]\n", contrast);
        return (-ERANGE);
    }

    if (0 == contrast) {
        reg5588 = 0x1;
    } else {
        reg5588 = 0x41;
    }
    y_gain = 0x20 + 0x4 * contrast;

    i2cc_set_reg(client, 0x5001, 0xff);
    i2cc_set_reg(client, 0x5580, 0x04);
    i2cc_set_reg(client, 0x5586, y_gain);
    i2cc_set_reg(client, 0x5585, y_gain);
    i2cc_set_reg(client, 0x5588, reg5588);
    priv->contrast = contrast;

    OV_INFO("contrast:%d, y_gain:0x%x, reg5588:0x%x\n", contrast, y_gain, reg5588);
    return (0);
}


/* auto, manual seperated is ok?? */
static int ov5640_set_saturation(struct i2c_client *client, int saturation)
{
    struct ov5640_priv *priv = to_ov5640(client);
    unsigned char uv_max, uv_min, reg5588;

    if (saturation < -4 || 4 < saturation) {
        OV_ERR("saturation - %d is out of range[-4, 4]\n", saturation);
        return (-ERANGE);
    }

    if (0 == saturation) {  /* different from application notes */
        uv_max = 0x40;   /* max value for UV adjust */
        uv_min = 0x10;   /* min value for UV adjust */
        reg5588 = 0x01;  /* bit[6]==0, auto saturation */
    } else {
        uv_max = 0x40 + 0x10 * saturation; /* U sat. */
        uv_min = uv_max; /* v sat */
        reg5588 = 0x41;  /* bit[6]==1, manual saturation */
    }

    i2cc_set_reg(client, 0x5001, 0xff);  /* init is 0xa3 */
    i2cc_set_reg(client, 0x5583, uv_max);
    i2cc_set_reg(client, 0x5584, uv_min);
    i2cc_set_reg(client, 0x5580, 0x02);  /* bit[1], enable(1)/disabe(0) saturation */
    i2cc_set_reg(client, 0x5588, reg5588); 
    priv->saturation = saturation;
    OV_INFO("saturation:%d\n", saturation);
    return (0);
}

/* XXX:effect is reversed to note's picture exept -180. check it */
static int ov5640_set_hue(struct i2c_client *client, int hue)
{
    struct ov5640_priv *priv = to_ov5640(client);
    unsigned char reg5581, reg5582, reg5588;

    switch (hue) {
        case -180:
            reg5581 = 0x80;
            reg5582 = 0x00;
            reg5588 = 0x32;
            break;
        case -150:
            reg5581 = 0x6f;
            reg5582 = 0x40;
            reg5588 = 0x32;
            break;
        case -120:
            reg5581 = 0x40;
            reg5582 = 0x6f;
            reg5588 = 0x32;
            break;
        case -90:
            reg5581 = 0x00;
            reg5582 = 0x80;
            reg5588 = 0x02;
            break;
        case -60:
            reg5581 = 0x40;
            reg5582 = 0x6f;
            reg5588 = 0x02;
            break;
        case -30:
            reg5581 = 0x6f;
            reg5582 = 0x40;
            reg5588 = 0x02;
            break;
        case 0:
            reg5581 = 0x80;
            reg5582 = 0x00;
            reg5588 = 0x01;
            break;
        case 30:
            reg5581 = 0x6f;
            reg5582 = 0x40;
            reg5588 = 0x01;
            break;
        case 60:
            reg5581 = 0x40;
            reg5582 = 0x6f;
            reg5588 = 0x01;
            break;
        case 90:
            reg5581 = 0x00;
            reg5582 = 0x80;
            reg5588 = 0x31;
            break;
        case 120:
            reg5581 = 0x40;
            reg5582 = 0x6f;
            reg5588 = 0x31;
            break;
        case 150:
            reg5581 = 0x6f;
            reg5582 = 0x40;
            reg5588 = 0x31;
            break;
        default:
            OV_ERR("hue - %d is out of range[-180, 150]/step-30\n", hue);
            return (-ERANGE);
    }

    i2cc_set_reg(client, 0x5001, 0xff);
    i2cc_set_reg(client, 0x5580, 0x01);  /* XXXX:diff. from defualt value */
    i2cc_set_reg(client, 0x5581, reg5581);  /* hue cos coefficient */
    i2cc_set_reg(client, 0x5582, reg5582);  /* hue sin coefficient */
    i2cc_set_reg(client, 0x5588, reg5588);
    priv->hue = hue;
    OV_INFO("hue: %d, 5581:0x%x, 5582:0x%x, 5588:0x%x\n", 
        hue, reg5581, reg5582, reg5588);

    return (0);
}


/* default value here is different from init one. */
static int ov5640_set_exposure_level(struct i2c_client *client, int level)
{
    struct ov5640_priv *priv = to_ov5640(client);
    unsigned char reg3a0f, reg3a10;
    unsigned char reg3a1b, reg3a1e;
    unsigned char reg3a11, reg3a1f;

    reg3a0f = 0x38 + 0x8 * level;
    reg3a10 = 0x30 + 0x8 * level;
    reg3a1b = reg3a0f;
    reg3a1e = reg3a10;
    reg3a1f = 0x10;

    switch (level) {
        case -5:  /* -1.7EV */
            reg3a11 = 0x20;
            break;
        case -4:  /* -1.3EV */
            reg3a11 = 0x30;
            break;
        case -3:  /* -1.0EV */
            reg3a11 = 0x41;
            break;
        case -2:  /* -0.7EV */
            reg3a11 = 0x51;
            break;
        case -1:  /* -0.3EV */
            reg3a11 = 0x61;
            break;
        case 0:  /* 0EV, default */
            reg3a11 = 0x61;
            break;
        case 1:  /* 0.3EV */
            reg3a11 = 0x71;
            break;
        case 2:  /* 0.7EV */
            reg3a11 = 0x80;
            reg3a1f = 0x20;
            break;
        case 3:  /* 1.0EV */
            reg3a11 = 0x90;
            reg3a1f = 0x20;
            break;
        case 4:  /* 1.3EV */
            reg3a11 = 0x91;
            reg3a1f = 0x20;
            break;
        case 5:  /* 1.7EV */
            reg3a11 = 0xa0;
            reg3a1f = 0x20;
            break;
        default:
            OV_ERR("exposure - %d is out of range[-5, 5]\n", level);
            return (-ERANGE);
    }

    OV_INFO("exposure: %d, 0x3a0f:0x%x, 0x3a10:0x%x\n", level, reg3a0f, reg3a10);
    //OV_INFO("0x3a1b:0x%x, 0x3a1e:0x%x\n", reg3a1b, reg3a1e);
    OV_INFO("0x3a11:0x%x, 0x3a1f:0x%x\n\n", reg3a11, reg3a1f);

    i2cc_set_reg(client, 0x3a0f, reg3a0f);  /* stable range high limit(enter) */
    i2cc_set_reg(client, 0x3a10, reg3a10);  /* stable range low limit(enter) */
    i2cc_set_reg(client, 0x3a11, reg3a11);  /* fast zone high limit */
    i2cc_set_reg(client, 0x3a1b, reg3a1b);  /* stable range high limit(go out) */
    i2cc_set_reg(client, 0x3a1e, reg3a1e);  /* stable range low limit(go out) */
    i2cc_set_reg(client, 0x3a1f, reg3a1f);  /* fast zone low limit */
    priv->exposure = level;
    
    return (0);
}


#define OV5640_FLIP_VAL  ((unsigned char)0x06)
#define OV5640_FLIP_MASK (~(OV5640_FLIP_VAL))
static int ov5640_set_flip(struct i2c_client *client, struct v4l2_control *ctrl)
{
    struct ov5640_priv *priv = to_ov5640(client);
    unsigned char reg3820, reg3821;

    OV_INFO("old flag: %d\n", priv->flip_flag);
    
    switch (ctrl->id) {
        case V4L2_CID_HFLIP:
            if (ctrl->value) {
                priv->flip_flag |= OV5640_HFLIP;
            } else {
                priv->flip_flag &= ~OV5640_HFLIP;
            }
            break;
	    case V4L2_CID_VFLIP:
            if (ctrl->value) {
                priv->flip_flag |= OV5640_VFLIP;
            } else {
                priv->flip_flag &= ~OV5640_VFLIP;
            }
            break;
        default:
            OV_ERR("set flip out of range\n");
            return (-ERANGE);
    }

    OV_INFO("new flag: %d\n", priv->flip_flag);

    i2cc_get_reg(client, 0x3820, &reg3820);
    i2cc_get_reg(client, 0x3821, &reg3821);
    
    if (priv->flip_flag & OV5640_VFLIP) {
        reg3820 |= OV5640_FLIP_VAL;
    } else {
        reg3820 &= OV5640_FLIP_MASK;
    }
    
    if (priv->flip_flag & OV5640_HFLIP) {
        reg3821 |= OV5640_FLIP_VAL;
    } else {
        reg3821 &= OV5640_FLIP_MASK;
    }

    /* have a bug which flip a half picture only. */
    //i2cc_set_reg(client, 0x3212, 0x00);   /* enable group0, when add no flip */
    i2cc_set_reg(client, 0x3820, reg3820); 
    i2cc_set_reg(client, 0x3821, reg3821);
    //i2cc_set_reg(client, 0x3212, 0x10);   /* end group0 */
    //i2cc_set_reg(client, 0x3212, 0xa1);   /* launch group1 */
    OV_INFO("0x3820:0x%x, 0x3821:0x%x\n", reg3820, reg3821);
    
    return (0);
}

static int ov5640_set_sharpness(struct i2c_client *client, int sharp)
{
    struct ov5640_priv *priv = to_ov5640(client);
    unsigned char reg5302;

    switch (sharp) {
        case -1:  /*auto sharpness*/
            break;
        case 0:   /* sharpness off */
            reg5302 = 0x00;
            break;
        case 1:
            reg5302 = 0x02;
            break;
        case 2:
            reg5302 = 0x04;
            break;
        case 3:
            reg5302 = 0x08;
            break;
        case 4:
            reg5302 = 0x0c;
            break;
        case 5:
            reg5302 = 0x10;
            break;
        case 6:
            reg5302 = 0x14;
            break;
        case 7:
            reg5302 = 0x18;
            break;
        case 8:
            reg5302 = 0x20;
            break;
        default:
            OV_ERR("set sharpness is out of range - %d[-1,8]\n", sharp);
            return (-ERANGE);

    }

    if (0 <= sharp) {
        i2cc_set_reg(client, 0x5308, 0x65);
        i2cc_set_reg(client, 0x5302, reg5302);
        OV_INFO("sharp:%d, 5302:0x%x\n", sharp, reg5302);
    } else {
        const struct regval ov5640_auto_sharpness[] = {
            {0x5308, 0x25},
            {0x5300, 0x08},
            {0x5301, 0x30},
            {0x5302, 0x10},
            {0x5303, 0x00},
            {0x5309, 0x08},
            {0x530a, 0x30},
            {0x530b, 0x04},
            {0x530c, 0x06},
        };
        int len = ARRAY_SIZE(ov5640_auto_sharpness);
        write_regs(client, ov5640_auto_sharpness, len);
        OV_INFO("sharp:%d, len:%d\n", sharp, len);
    }
    priv->sharpness = sharp;
    
    return (0);
}


static int ov5640_set_colorfx(struct i2c_client *client, int effect)
{
    struct ov5640_priv *priv = to_ov5640(client);
    unsigned char reg5583, reg5584, reg5001, reg5580;

    reg5001 = 0xff;
    reg5580 = 0x18;
    switch (effect) {
        case 0: /* normal */
            reg5001 = 0x7f;
            reg5580 = 0x00;
            break;
        case 1: /* black and white */
            reg5583 = 0x80;
            reg5584 = 0x80;
            break;
        case 2: /* sepia , antique */
            reg5583 = 0x40;
            reg5584 = 0xa0;
            break;
        case 3: /* negative */
            reg5001 = 0xff;
            reg5580 = 0x40;
            break;
        case 4: /* bluish */
            reg5583 = 0xa0;
            reg5584 = 0x40;
            break;
        case 5: /* greenish */
            reg5583 = 0x60;
            reg5584 = 0x60;
            break;
        case 6: /* reddish */
            reg5583 = 0x80;
            reg5584 = 0xc0;
            break;
        default:
            OV_ERR("set color effects out of range - %d[0,6]\n", effect);
            return (-ERANGE);

    }

    i2cc_set_reg(client, 0x5001, reg5001);
    i2cc_set_reg(client, 0x5580, reg5580);
    OV_INFO("effect:%d, 0x5001:0x%x, 0x5580:0x%x\n", effect, reg5001, reg5580);
    if (0 != effect && 3 != effect) {
        i2cc_set_reg(client, 0x5583, reg5583);
        i2cc_set_reg(client, 0x5584, reg5584); 
        OV_INFO("0x5583:0x%x, 0x5584:0x%x\n", reg5583, reg5584);
    }

    priv->colorfx = effect;
    return (0);

}

/* Must be sorted from low to high control ID! */
static const u32 ov5640_user_ctrls[] = {
	V4L2_CID_USER_CLASS,
	V4L2_CID_BRIGHTNESS,
	V4L2_CID_CONTRAST,
	V4L2_CID_SATURATION,
	V4L2_CID_HUE,
//	V4L2_CID_BLACK_LEVEL,
	V4L2_CID_AUTO_WHITE_BALANCE,
//	V4L2_CID_DO_WHITE_BALANCE,
//	V4L2_CID_RED_BALANCE,
//	V4L2_CID_BLUE_BALANCE,
//	V4L2_CID_GAMMA,
	V4L2_CID_EXPOSURE,
	V4L2_CID_AUTOGAIN,
	V4L2_CID_GAIN,
	V4L2_CID_HFLIP,
	V4L2_CID_VFLIP,
	V4L2_CID_POWER_LINE_FREQUENCY,
//	V4L2_CID_HUE_AUTO,
	V4L2_CID_WHITE_BALANCE_TEMPERATURE,
	V4L2_CID_SHARPNESS,
//	V4L2_CID_BACKLIGHT_COMPENSATION,
//	V4L2_CID_CHROMA_AGC,
//	V4L2_CID_CHROMA_GAIN,
//	V4L2_CID_COLOR_KILLER,
	V4L2_CID_COLORFX,
//	V4L2_CID_AUTOBRIGHTNESS,
	V4L2_CID_BAND_STOP_FILTER,
//	V4L2_CID_ROTATE,
//	V4L2_CID_BG_COLOR,
	0,
};

static const u32 ov5640_camera_ctrls[] = {
	V4L2_CID_CAMERA_CLASS,
	V4L2_CID_EXPOSURE_AUTO,
//	V4L2_CID_EXPOSURE_ABSOLUTE,
//	V4L2_CID_EXPOSURE_AUTO_PRIORITY,
//	V4L2_CID_PAN_RELATIVE,
//	V4L2_CID_TILT_RELATIVE,
//	V4L2_CID_PAN_RESET,
//	V4L2_CID_TILT_RESET,
//	V4L2_CID_PAN_ABSOLUTE,
//	V4L2_CID_TILT_ABSOLUTE,
//	V4L2_CID_FOCUS_ABSOLUTE,
//	V4L2_CID_FOCUS_RELATIVE,
//	V4L2_CID_FOCUS_AUTO,
//	V4L2_CID_ZOOM_ABSOLUTE,
//	V4L2_CID_ZOOM_RELATIVE,
//	V4L2_CID_ZOOM_CONTINUOUS,
//	V4L2_CID_IRIS_ABSOLUTE,
//	V4L2_CID_IRIS_RELATIVE,
//	V4L2_CID_PRIVACY,
//cym	V4L2_CID_SCENE_EXPOSURE,
	0,
};


static const u32 *ov5640_ctrl_classes[] = {
	ov5640_user_ctrls,
	ov5640_camera_ctrls,
	NULL,
};

static int ov5640_queryctrl(struct v4l2_subdev *sd,
		struct v4l2_queryctrl *qc)
{
	//struct i2c_client *client = v4l2_get_subdevdata(sd);

	qc->id = v4l2_ctrl_next(ov5640_ctrl_classes, qc->id);
	if (qc->id == 0) {
		return (-EINVAL);
	}
    OV_INFO("%s: id-%s\n", __func__, v4l2_ctrl_get_name(qc->id));
	/* Fill in min, max, step and default value for these controls. */
	switch (qc->id) {
	/* Standard V4L2 controls */
	case V4L2_CID_USER_CLASS:
		return v4l2_ctrl_query_fill(qc, 0, 0, 0, 0);

	case V4L2_CID_BRIGHTNESS:
		return v4l2_ctrl_query_fill(qc, -4, 4, 1, 0);

	case V4L2_CID_CONTRAST:
		return v4l2_ctrl_query_fill(qc, -4, 4, 1, 0);

	case V4L2_CID_SATURATION:
		return v4l2_ctrl_query_fill(qc, -4, 4, 1, 0);

	case V4L2_CID_HUE:
		return v4l2_ctrl_query_fill(qc, -180, 150, 30, 0);
#if 0

//	case V4L2_CID_BLACK_LEVEL:

	case V4L2_CID_AUTO_WHITE_BALANCE:
		return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1);

//	case V4L2_CID_DO_WHITE_BALANCE:
//	case V4L2_CID_RED_BALANCE:
//	case V4L2_CID_BLUE_BALANCE:
//	case V4L2_CID_GAMMA:
#endif
	case V4L2_CID_EXPOSURE:
		return v4l2_ctrl_query_fill(qc, -5, 5, 1, 0);
#if 0
	case V4L2_CID_AUTOGAIN:
		return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1);
	case V4L2_CID_GAIN:
		return v4l2_ctrl_query_fill(qc, 0, 0xFFU, 1, 128);
#endif
	case V4L2_CID_HFLIP:
	case V4L2_CID_VFLIP:
		return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0);
#if 0
	case V4L2_CID_POWER_LINE_FREQUENCY:
		return v4l2_ctrl_query_fill(qc, 0, 2, 1, 1);
//	case V4L2_CID_HUE_AUTO:

	case V4L2_CID_WHITE_BALANCE_TEMPERATURE:
		return v4l2_ctrl_query_fill(qc, 0, 3, 1, 0);
#endif
	case V4L2_CID_SHARPNESS:
		return v4l2_ctrl_query_fill(qc, -1, 8, 1, -1);
//	case V4L2_CID_BACKLIGHT_COMPENSATION:
//	case V4L2_CID_CHROMA_AGC:
//	case V4L2_CID_CHROMA_GAIN:
//	case V4L2_CID_COLOR_KILLER:

	case V4L2_CID_COLORFX:
		return v4l2_ctrl_query_fill(qc, 0, 6, 1, 0);
//	case V4L2_CID_AUTOBRIGHTNESS:
#if 0
	case V4L2_CID_BAND_STOP_FILTER:
		return v4l2_ctrl_query_fill(qc, 0, 63, 1, 2);

//	case V4L2_CID_ROTATE:
//	case V4L2_CID_BG_COLOR:
#endif
	case V4L2_CID_CAMERA_CLASS:
		return v4l2_ctrl_query_fill(qc, 0, 0, 0, 0);
#if 0
	case V4L2_CID_EXPOSURE_AUTO:
		return v4l2_ctrl_query_fill(qc, 0, 1, 1, 1);

//	case V4L2_CID_EXPOSURE_ABSOLUTE:
//	case V4L2_CID_EXPOSURE_AUTO_PRIORITY:
//	case V4L2_CID_PAN_RELATIVE:
//	case V4L2_CID_TILT_RELATIVE:
//	case V4L2_CID_PAN_RESET:
//	case V4L2_CID_TILT_RESET:
//	case V4L2_CID_PAN_ABSOLUTE:
//	case V4L2_CID_TILT_ABSOLUTE:
//	case V4L2_CID_FOCUS_ABSOLUTE:
//	case V4L2_CID_FOCUS_RELATIVE:
//	case V4L2_CID_FOCUS_AUTO:
//	case V4L2_CID_ZOOM_ABSOLUTE:
//	case V4L2_CID_ZOOM_RELATIVE:
//	case V4L2_CID_ZOOM_CONTINUOUS:
//	case V4L2_CID_IRIS_ABSOLUTE:
//	case V4L2_CID_IRIS_RELATIVE:
//	case V4L2_CID_PRIVACY:

	case V4L2_CID_SCENE_EXPOSURE:
		return v4l2_ctrl_query_fill(qc, 0, 1, 1, 0);
#endif
	default:
		OV_ERR("invalid control ctrl: %s\n", v4l2_ctrl_get_name(qc->id));
		qc->flags |= V4L2_CTRL_FLAG_DISABLED;
		return (-EINVAL);
	}

	return (0);
}


static int ov5640_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
{
	struct i2c_client *client = v4l2_get_subdevdata(sd);
	//struct ov5640_priv *priv = to_ov5640(client);
	int ret = 0;
	//int val = 0;

	/* add by cym 20130812 */
	int err = 0;
	//int value = ctrl->value;
	/* end add */

    OV_INFO("%s: control ctrl- %s\n", __func__, v4l2_ctrl_get_name(ctrl->id));
	printk("%s: control ctrl- id = %d\n", __func__, ctrl->id-V4L2_CID_PRIVATE_BASE);

	switch (ctrl->id) {
	case V4L2_CID_BRIGHTNESS:
		ov5640_set_brightness(client, ctrl->value);
		break;

	case V4L2_CID_CONTRAST:
		ov5640_set_contrast(client, ctrl->value);
		break;

	case V4L2_CID_SATURATION:
		ov5640_set_saturation(client, ctrl->value);
		break;

	case V4L2_CID_HUE:
		ov5640_set_hue(client, ctrl->value);
		break;
#if 0

//	case V4L2_CID_BLACK_LEVEL:
//		ov5640_set_black_level(sd, ctrl->value);
//		break;

	case V4L2_CID_AUTO_WHITE_BALANCE:
		ov5640_set_awb(client, ctrl->value);
		break;
//	case V4L2_CID_DO_WHITE_BALANCE:
//		ov5640_set_do_white_balance(sd, ctrl->value);
//		break;
//	case V4L2_CID_RED_BALANCE:
//		ov5640_set_red_balance(sd, ctrl->value);
//		break;
//	case V4L2_CID_BLUE_BALANCE:
//		ov5640_set_blue_balance(sd, ctrl->value);
//		break;
//	case V4L2_CID_GAMMA:
//		ov5640_set_gamma(sd, ctrl->value);
//		break;
#endif
	case V4L2_CID_EXPOSURE:
		ov5640_set_exposure_level(client, ctrl->value);
		break;
#if 0
	case V4L2_CID_AUTOGAIN:
		ov5640_set_autogain(sd, ctrl->value);
		break;
	case V4L2_CID_GAIN:
		ov5640_set_gain(sd, ctrl->value);
		break;
#endif
	case V4L2_CID_HFLIP:
	case V4L2_CID_VFLIP:
        ov5640_set_flip(client, ctrl);
        break;
#if 0
	case V4L2_CID_POWER_LINE_FREQUENCY:
		ov5640_set_power_line_frequency(sd, ctrl->value);
		break;
//	case V4L2_CID_HUE_AUTO:
//		ov5640_set_hue_auto(sd, ctrl->value);
//		break;

	case V4L2_CID_WHITE_BALANCE_TEMPERATURE:
		set_white_balance_temperature(client, ctrl->value);
		break;
#endif
	case V4L2_CID_SHARPNESS:
		ov5640_set_sharpness(client, ctrl->value);
		break;
//	case V4L2_CID_BACKLIGHT_COMPENSATION:
//		ov5640_set_backlight_compensation(sd, ctrl->value);
//		break;
//	case V4L2_CID_CHROMA_AGC:
//		ov5640_set_chroma_agc(sd, ctrl->value);
//		break;
//	case V4L2_CID_CHROMA_GAIN:
//		ov5640_set_chroma_gain(sd, ctrl->value);
//		break;
//	case V4L2_CID_COLOR_KILLER:
//		ov5640_set_color_killer(sd, ctrl->value);
//		break;

	case V4L2_CID_COLORFX:
		ov5640_set_colorfx(client, ctrl->value);
		break;
#if 0
//	case V4L2_CID_AUTOBRIGHTNESS:
//		ov5640_set_autobrightness(sd, ctrl->value);
//		break;

	case V4L2_CID_BAND_STOP_FILTER:
		ov5640_set_band_stop_filter(sd, ctrl->value);
		break;

//	case V4L2_CID_ROTATE:
//		ov5640_set_rotate(sd, ctrl->value);
//		break;
//	case V4L2_CID_BG_COLOR:
//		ov5640_set_bg_color(sd, ctrl->value);
//		break;

	case V4L2_CID_EXPOSURE_AUTO:
		ov5640_set_exposure_auto(sd, ctrl->value);
		break;

//	case V4L2_CID_EXPOSURE_ABSOLUTE:
//	case V4L2_CID_EXPOSURE_AUTO_PRIORITY:
//	case V4L2_CID_PAN_RELATIVE:
//	case V4L2_CID_TILT_RELATIVE:
//	case V4L2_CID_PAN_RESET:
//	case V4L2_CID_TILT_RESET:
//	case V4L2_CID_PAN_ABSOLUTE:
//	case V4L2_CID_TILT_ABSOLUTE:
//	case V4L2_CID_FOCUS_ABSOLUTE:
//	case V4L2_CID_FOCUS_RELATIVE:
//	case V4L2_CID_FOCUS_AUTO:
//	case V4L2_CID_ZOOM_ABSOLUTE:
//	case V4L2_CID_ZOOM_RELATIVE:
//	case V4L2_CID_ZOOM_CONTINUOUS:
//	case V4L2_CID_IRIS_ABSOLUTE:
//	case V4L2_CID_IRIS_RELATIVE:
//	case V4L2_CID_PRIVACY:

	case V4L2_CID_SCENE_EXPOSURE:
		ov5640_set_scene_exposure(sd, ctrl->value);
		break;
#endif
	/* add by cym 20130812 */
	case V4L2_CID_CAMERA_SET_AUTO_FOCUS:
        {
                printk("auto focus......\n");

                err = ov5640_sensor_s_single_af(sd);

           //      OV5640_FOCUS_AD5820_Single_Focus();
             //   OV5640_FOCUS_AD5820_Constant_Focus();

         }

            break;
	/* end add */
	default:
		OV_ERR("invalid control ctrl: %s\n", v4l2_ctrl_get_name(ctrl->id));
		return (-EINVAL);
	}
    
	return (ret);
}

static int ov5640_init(struct v4l2_subdev *sd, u32 val)
{
	struct i2c_client *client = v4l2_get_subdevdata(sd);
	struct ov5640_priv *priv = to_ov5640(client);
    	unsigned char pid;
    	unsigned char version;
	//int err = -EINVAL;

	/* add by cym 20121121 */
	ov5640_power(1);
	/* end add */

        //dg add 2015-07-15
        i2cc_set_reg(client, 0x3103,0x11);
        i2cc_set_reg(client, 0x3008,0x82);
        mdelay(20);




	 // check and show product ID and manufacturer ID
	i2cc_get_reg(client, 0x300a, &pid);
	i2cc_get_reg(client, 0x300b, &version);

	printk("%s: version = 0x%x%x\n", __FUNCTION__, pid, version);

	if (OV5640 != VERSION(pid, version)) {
	    OV_ERR("ov5640 probed failed!!\n");
	    return (-ENODEV);
	}

	priv->model = 1;//cym V4L2_IDENT_OV5640;


	//ov5640_sensor_download_af_fw(sd);

	//ov5640_sensor_s_single_af(sd);




        //dg add  2015-07-25
        OV5640_FOCUS_AD5820_Init();
        OV5640YUV_Sensor_Dvp_Init();
        down_af_firmware_flag =1;


	INFO_BLUE("ov5640 device probed success\n");

	return 0;
}

static int ov5640_g_ctrl(struct v4l2_subdev *sd, struct v4l2_control *ctrl)
{
	struct i2c_client *client = v4l2_get_subdevdata(sd);
	struct ov5640_priv *priv = to_ov5640(client);

	int err = 0;

    OV_INFO("%s: control ctrl- %s\n", __func__, v4l2_ctrl_get_name(ctrl->id));
    	printk("%s: control ctrl- id = %d\n", __func__, ctrl->id);
		
    switch (ctrl->id) {

    case V4L2_CID_BRIGHTNESS:
        ctrl->value = priv->brightness;
        break;

    case V4L2_CID_CONTRAST:
        ctrl->value = priv->contrast;
        break;

    case V4L2_CID_SATURATION:
        ctrl->value = priv->saturation;
        break;
    case V4L2_CID_HUE:
        ctrl->value = priv->hue;
        break;
        
    //  case V4L2_CID_BLACK_LEVEL:
    //      ctrl->value = priv->black_level;
    //      break;
#if 0
    case V4L2_CID_AUTO_WHITE_BALANCE:
        ctrl->value = priv->auto_white_balance;
        break;
    //  case V4L2_CID_DO_WHITE_BALANCE:
    //      ctrl->value = priv->do_white_balance;
    //      break;
    //  case V4L2_CID_RED_BALANCE:
    //      ctrl->value = priv->red_balance;
    //      break;
    //  case V4L2_CID_BLUE_BALANCE:
    //      ctrl->value = priv->blue_balance;
    //      break;
    //  case V4L2_CID_GAMMA:
    //      ctrl->value = priv->gamma;
    //      break;
#endif
    case V4L2_CID_EXPOSURE:
        ctrl->value = priv->exposure;
        break;
#if 0
    case V4L2_CID_AUTOGAIN:
    ctrl->value = priv->autogain;
    break;
    case V4L2_CID_GAIN:
    ctrl->value = priv->gain;
    break;
#endif
    case V4L2_CID_HFLIP:
        ctrl->value = !!(priv->flip_flag & OV5640_HFLIP);
        break;
    case V4L2_CID_VFLIP:
        ctrl->value = !!(priv->flip_flag & OV5640_VFLIP);
        break;
#if 0
    case V4L2_CID_POWER_LINE_FREQUENCY:
    ctrl->value = priv->power_line_frequency;
    break;
    //  case V4L2_CID_HUE_AUTO:
    //      ctrl->value = priv->hue_auto;
    //      break;

    case V4L2_CID_WHITE_BALANCE_TEMPERATURE:
        ctrl->value = priv->white_balance_temperature;
        break;
#endif
    case V4L2_CID_SHARPNESS:
        ctrl->value = priv->sharpness;
        break;
    //  case V4L2_CID_BACKLIGHT_COMPENSATION:
    //      ctrl->value = priv->backlight_compensation;
    //      break;
    //  case V4L2_CID_CHROMA_AGC:
    //      ctrl->value = priv->chroma_agc;
    //      break;
    //  case V4L2_CID_CHROMA_GAIN:
    //      ctrl->value = priv->chroma_gain;
    //      break;
    //  case V4L2_CID_COLOR_KILLER:
    //      ctrl->value = priv->color_killer;
    //      break;

    case V4L2_CID_COLORFX:
        ctrl->value = priv->colorfx;
        break;
#if 0
    //  case V4L2_CID_AUTOBRIGHTNESS:
    //      ctrl->value = priv->autobrightness;
    //      break;
    
    case V4L2_CID_BAND_STOP_FILTER:
    ctrl->value = priv->band_stop_filter;
    break;
    
    //  case V4L2_CID_ROTATE:
    //      ctrl->value = priv->rotate;
    //      break;
    //  case V4L2_CID_BG_COLOR:
    //      ctrl->value = priv->bg_color;
    //      break;
    
    case V4L2_CID_EXPOSURE_AUTO:
    ctrl->value = priv->exposure_auto;
    break;
    
    //  case V4L2_CID_EXPOSURE_ABSOLUTE:
    //  case V4L2_CID_EXPOSURE_AUTO_PRIORITY:
    //  case V4L2_CID_PAN_RELATIVE:
    //  case V4L2_CID_TILT_RELATIVE:
    //  case V4L2_CID_PAN_RESET:
    //  case V4L2_CID_TILT_RESET:
    //  case V4L2_CID_PAN_ABSOLUTE:
    //  case V4L2_CID_TILT_ABSOLUTE:
    //  case V4L2_CID_FOCUS_ABSOLUTE:
    //  case V4L2_CID_FOCUS_RELATIVE:
    //  case V4L2_CID_FOCUS_AUTO:
    //  case V4L2_CID_ZOOM_ABSOLUTE:
    //  case V4L2_CID_ZOOM_RELATIVE:
    //  case V4L2_CID_ZOOM_CONTINUOUS:
    //  case V4L2_CID_IRIS_ABSOLUTE:
    //  case V4L2_CID_IRIS_RELATIVE:
    //  case V4L2_CID_PRIVACY:
    
    case V4L2_CID_SCENE_EXPOSURE:
    ctrl->value = priv->scene_exposure;
    break;
#endif

	/* add by cym 20130829 */
        case V4L2_CID_CAMERA_AUTO_FOCUS_RESULT:

               //android4.0 use this, it is very important for take picture,android4.4 not use.
		err = ov5640_get_auto_focus_result(sd, ctrl);
		break;
	/* end add */

    default:
    OV_ERR("invalid control ctrl: %s\n", v4l2_ctrl_get_name(ctrl->id));
    return (-EINVAL);
    }

    return (0);
}


static int ov5640_s_ext_ctrls(struct v4l2_subdev *sd, 
    struct v4l2_ext_controls *ctrls)
{
	//struct i2c_client *client = v4l2_get_subdevdata(sd);
	struct v4l2_control ctrl;

	int i;
	int err = 0;

	if ((ctrls->ctrl_class != V4L2_CTRL_CLASS_USER)
		&& (ctrls->ctrl_class != V4L2_CTRL_CLASS_CAMERA)) {
		OV_ERR("ctrl class[%s] is illegal.\n", v4l2_ctrl_get_name(ctrls->ctrl_class));
		return (-EINVAL);
	}

	for (i = 0; i < ctrls->count; i++) {
		ctrl.id = ctrls->controls[i].id;
		ctrl.value = ctrls->controls[i].value;
		err = ov5640_s_ctrl(sd, &ctrl);
		//ctrls->controls[i].value = ctrl.value;
		if (err) {
			ctrls->error_idx = i;
			break;
		}
	}

	return (err);
}

static int ov5640_g_ext_ctrls(struct v4l2_subdev *sd, 
    struct v4l2_ext_controls *ctrls)
{
	//struct i2c_client *client = v4l2_get_subdevdata(sd);
	struct v4l2_control ctrl;

	int i;
	int err = 0;

	if ((ctrls->ctrl_class != V4L2_CTRL_CLASS_USER)
		&& (ctrls->ctrl_class != V4L2_CTRL_CLASS_CAMERA)) {
		OV_ERR("ctrl class[%s] is illegal.\n", v4l2_ctrl_get_name(ctrls->ctrl_class));
		return (-EINVAL);
	}

	for (i = 0; i < ctrls->count; i++) {
		ctrl.id = ctrls->controls[i].id;
		//ctrl.value = ctrls->controls[i].value;
		err = ov5640_g_ctrl(sd, &ctrl);
		ctrls->controls[i].value = ctrl.value;
		if (err) {
			ctrls->error_idx = i;
			break;
		}
	}

	return (err);
}


static int ov5640_try_ctrl(struct v4l2_subdev *sd,
    struct v4l2_ext_control *ctrl)
{
	struct v4l2_queryctrl qctrl;
	const char **menu_items = NULL;
	int err;

	qctrl.id = ctrl->id;
	err = ov5640_queryctrl(sd, &qctrl);
	if (err)
		return (err);
	if (qctrl.type == V4L2_CTRL_TYPE_MENU)
		menu_items = v4l2_ctrl_get_menu(qctrl.id);
	return v4l2_ctrl_check(ctrl, &qctrl, menu_items);
}

static int ov5640_try_ext_ctrls(struct v4l2_subdev *sd, 
    struct v4l2_ext_controls *ctrls)
{
	//struct i2c_client *client = v4l2_get_subdevdata(sd);

	int i;
	int err = 0;

	if ((ctrls->ctrl_class != V4L2_CTRL_CLASS_USER)
		&& (ctrls->ctrl_class != V4L2_CTRL_CLASS_CAMERA)) {
		OV_ERR("ctrl_class[%s] is illegal.\n", v4l2_ctrl_get_name(ctrls->ctrl_class));
		return (-EINVAL);
	}

	for (i = 0; i < ctrls->count; i++) {
		err = ov5640_try_ctrl(sd, &ctrls->controls[i]);
		if (err) {
			ctrls->error_idx = i;
			break;
		}
	}
	return (err);
}


#ifdef CONFIG_VIDEO_ADV_DEBUG

static int ov5640_g_register(struct v4l2_subdev *sd,
    struct v4l2_dbg_register *reg)
{
    struct i2c_client *client = v4l2_get_subdevdata(sd);
    unsigned char val;
    int err;

    reg->size = 2;
    if (reg->reg > 0x603f) {
        return (-EINVAL);
    }
    err = i2cc_get_reg(client, reg->reg, &val);
    if (err) {
        return (err);
    }
    reg->val = val;
    return (0);
}

static int ov5640_s_register(struct v4l2_subdev *sd,
    struct v4l2_dbg_register *reg)
{
    struct i2c_client *client = v4l2_get_subdevdata(sd);

    if (reg->reg > 0x603f) {
        return (-EINVAL);
    }
    return (i2cc_set_reg(client, (unsigned short)reg->reg,(unsigned char)reg->val));
}

#endif

static struct soc_camera_ops ov5640_ops = {
    .set_bus_param = ov5640_set_bus_param,
    .query_bus_param = ov5640_query_bus_param,
    //.controls = ov5640_controls,
    //.num_controls = ARRAY_SIZE(ov5640_controls),
};


static struct v4l2_subdev_core_ops ov5640_subdev_core_ops = {
	.init = ov5640_init,	
	.g_ctrl		= ov5640_g_ctrl,
	.s_ctrl		= ov5640_s_ctrl,
	.queryctrl  = ov5640_queryctrl,
	.g_ext_ctrls = ov5640_g_ext_ctrls,
	.s_ext_ctrls = ov5640_s_ext_ctrls,
	.try_ext_ctrls = ov5640_try_ext_ctrls,
	.g_chip_ident	= ov5640_g_chip_ident,
#ifdef CONFIG_VIDEO_ADV_DEBUG
	.g_register	= ov5640_g_register,
	.s_register	= ov5640_s_register,
#endif
};

static struct v4l2_subdev_video_ops ov5640_subdev_video_ops = {
        .s_stream	=  ov5640_s_stream,
        .g_mbus_fmt	= ov5640_g_fmt,
	.s_mbus_fmt	= ov5640_s_fmt,
	.try_mbus_fmt	= ov5640_try_fmt,
	.cropcap	= ov5640_cropcap,
	.g_crop		= ov5640_g_crop,
	.enum_mbus_fmt	= ov5640_enum_fmt,
	.enum_framesizes = ov5640_enum_framesizes,
};


static struct v4l2_subdev_ops  ov5640_subdev_ops = {
    .core = &ov5640_subdev_core_ops,
    .video = &ov5640_subdev_video_ops,
};


#if 0  //remove by cym 20130807
static int ov5640_video_probe(struct soc_camera_device *icd, 
    struct i2c_client *client) 
{
    struct ov5640_priv *priv = to_ov5640(client);
    unsigned char pid;
    unsigned char version;

	/*
	 * We must have a parent by now. And it cannot be a wrong one.
	 * So this entire test is completely redundant.
	 */
    if (NULL == icd->dev.parent ||
        to_soc_camera_host(icd->dev.parent)->nr != icd->iface) {
        OV_ERR("error : has a wrong parent\n");
        //return (-ENODEV);
    }

    // check and show product ID and manufacturer ID
    i2cc_get_reg(client, 0x300a, &pid);
    i2cc_get_reg(client, 0x300b, &version);

    if (OV5640 != VERSION(pid, version)) {
        OV_ERR("ov5640 probed failed!!\n");
        return (-ENODEV);
    }
    
    priv->model = 1;//cym V4L2_IDENT_OV5640;

    INFO_BLUE("ov5640 device probed success\n");
    
    return (0);
}
#endif


static int ov5640_probe(struct i2c_client *client, 
    const struct i2c_device_id *did)
{
    struct ov5640_priv *priv;
	struct v4l2_subdev *sd = NULL;
    struct soc_camera_device *icd = client->dev.platform_data;
    //struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
    struct soc_camera_link *icl;
    int ret = 0;

    OV_INFO("ov5640 probe start...\n");
    if (NULL == icd) {
        ret = -EINVAL;
        OV_ERR("error: missing soc camera device\n");
        goto failed;
    }



    g_client=client;



	/* add by cym 20130605 */
#ifndef CONFIG_TC4_EVT
        ov_vdd18_cam_regulator = regulator_get(NULL, "vdd18_cam");

        if (IS_ERR(ov_vdd18_cam_regulator)) {
                printk("%s: failed to get %s\n", __func__, "vdd18_cam");
                ret = -ENODEV;
                goto err_regulator;
        }

        ov_vdd28_cam_regulator = regulator_get(NULL, "vdda28_2m");

        if (IS_ERR(ov_vdd28_cam_regulator)) {
                printk("%s: failed to get %s\n", __func__, "vdda28_2m");
                ret = -ENODEV;
                goto err_regulator;
        }

        ov_vddaf_cam_regulator = regulator_get(NULL, "vdd28_af");

        if (IS_ERR(ov_vddaf_cam_regulator)) {
                printk("%s: failed to get %s\n", __func__, "vdd28_af");
                ret = -ENODEV;
                goto err_regulator;
        }

        ov_vdd5m_cam_regulator = regulator_get(NULL, "vdd28_cam");

        if (IS_ERR(ov_vdd5m_cam_regulator)) {
                printk("%s: failed to get %s\n", __func__, "vdd28_cam");
                ret = -ENODEV;
                goto err_regulator;
        }

       // ov5640_power(1);
#endif
        /* end add */

    icl = to_soc_camera_link(icd);
    if (NULL == icl) {
        ret = -EINVAL;
        OV_ERR("error: missing soc camera link\n");
        //cym goto failed;
    }
    
    ret = i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA);
    if (0 == ret) {
        ret = -EINVAL;
        OV_ERR("I2C DOESN'T support I2C_FUNC_SMBUS_BYTE_DATA\n");
        goto failed;
    }

    priv = (struct ov5640_priv *)kzalloc(sizeof(struct ov5640_priv), GFP_KERNEL);
    if (NULL == priv) {
        ret = -ENOMEM;
        OV_ERR("alloc ov5640_priv struct failed!\n");
        goto failed;
    }

	sd = &priv->subdev;
	strcpy(sd->name, OV5640_I2C_NAME);

	v4l2_i2c_subdev_init(sd, client, &ov5640_subdev_ops);

	icd->ops = &ov5640_ops;

#if 0
	ret = ov5640_video_probe(icd, client);
	if (ret) {
		icd->ops = NULL;
		kfree(priv);
        OV_ERR("error : failed to probe camera device");
	}
#endif

    failed:
    	  //return (ret);
        return (0);
#ifndef CONFIG_TC4_EVT
err_regulator:
        ov5640_power(0);

        regulator_put(ov_vddaf_cam_regulator);
        regulator_put(ov_vdd5m_cam_regulator);

        /* add by cym 20130506 */
        regulator_put(ov_vdd18_cam_regulator);
        regulator_put(ov_vdd28_cam_regulator);
        /* end add */
        return ret;
#endif
}


static int ov5640_remove(struct i2c_client *client)
{
	struct ov5640_priv *priv = to_ov5640(client);
	struct soc_camera_device *icd = client->dev.platform_data;

	struct v4l2_subdev *sd = i2c_get_clientdata(client);

	v4l2_device_unregister_subdev(sd);

	//icd->ops = NULL;
	kfree(priv);
   	INFO_RED("ov5640 device removed!\n");

#ifndef CONFIG_TC4_EVT
        ov5640_power(0);

        regulator_put(ov_vddaf_cam_regulator);
        regulator_put(ov_vdd5m_cam_regulator);

        regulator_put(ov_vdd18_cam_regulator);
        regulator_put(ov_vdd28_cam_regulator);

	down_af_firmware_flag = 0;
        /* end add */
#endif

	return (0);
}

#if 0
static int ov5640_detect(struct i2c_client *client, struct i2c_board_info *info)
{
    strcpy(info->type, OV5640_I2C_NAME);
    return 0;
}
#endif

static const struct i2c_device_id ov5640_id[] = {
	{ OV5640_I2C_NAME, 0 },
	{ }
};
MODULE_DEVICE_TABLE(i2c, ov5640_id);


static const unsigned short ov5640_addrs[] = {
    OV5640_I2C_ADDR,
    I2C_CLIENT_END,
};

#if 0
struct i2c_board_info ov5640_info = {
    I2C_BOARD_INFO(OV5640_I2C_NAME, OV5640_I2C_ADDR),
};
#endif

static struct i2c_driver ov5640_i2c_driver = {
	.driver = {
		.name = OV5640_I2C_NAME,
        .owner = THIS_MODULE,
	},
	.class = I2C_CLASS_HWMON,
	.probe    = ov5640_probe,
	.remove   = ov5640_remove,
	.id_table = ov5640_id,
	.address_list = ov5640_addrs,
};


/*
 * module function
 */

static int __init ov5640_module_init(void)
{
    OV_INFO("install module\n");
	printk("%s\n", __FUNCTION__);

	return i2c_add_driver(&ov5640_i2c_driver);
}

static void __exit ov5640_module_exit(void)
{
    OV_INFO("uninstall module\n");
	i2c_del_driver(&ov5640_i2c_driver);
}

module_init(ov5640_module_init);
module_exit(ov5640_module_exit);

MODULE_DESCRIPTION("SoC Camera driver for ov5640");
MODULE_AUTHOR("caoym@topeet.com ");
MODULE_LICENSE("GPL v2");


